[java-idp-plugin-oidc-rp] branch main updated: Add basic framework for RequestObject encryption. Cleanup actions
Phil Smart
philip.smart at jisc.ac.uk
Tue Jul 12 13:58:29 UTC 2022
This is an automated email from the git hooks/post-receive script.
philsmart pushed a commit to branch main
in repository java-idp-plugin-oidc-rp.
View the commit online:
http://git.shibboleth.net/view/?p=java-idp-plugin-oidc-rp.git;a=commit;h=2f21443345a4bf780cda74ddc62a621698d1260a
The following commit(s) were added to refs/heads/main by this push:
new 2f21443 Add basic framework for RequestObject encryption. Cleanup actions
2f21443 is described below
commit 2f21443345a4bf780cda74ddc62a621698d1260a
Author: Phil Smart <philip.smart at jisc.ac.uk>
AuthorDate: Tue Jul 12 14:58:21 2022 +0100
Add basic framework for RequestObject encryption. Cleanup actions
The encryption support is nowhere near complete.
---
.../logic/EncryptRequestObjectPredicate.java | 45 ++++
...bjectEncryptionConfigurationLookupFunction.java | 96 +++++++
.../rp/context/OutboundMessageHandlerContext.java | 54 +---
.../AbstractOIDCAuthenticationRequestAction.java | 5 +-
...> AddAuthenticationContextClassReferences.java} | 5 +-
...opulateEndpointURI.java => AddEndpointURI.java} | 4 +-
...ompt.java => AddForceAuthenticationPrompt.java} | 7 +-
.../rp/impl/{PopulateNonce.java => AddNonce.java} | 9 +-
.../rp/{messaging => }/impl/AddRedirectURI.java | 64 +++--
...ypeAndMode.java => AddResponseTypeAndMode.java} | 57 +---
.../impl/{PopulateScopes.java => AddScopes.java} | 4 +-
.../oidc/rp/impl/AuthorizationController.java | 5 +-
.../authn/oidc/rp/impl/BuildRequestObject.java | 56 ++--
.../rp/impl/PopulateJWTEncryptionParameters.java | 294 +++++++++++++++++++++
...yingPartyProxyEncryptionParametersResolver.java | 68 +++++
...RelyingPartyProxySigningParametersResolver.java | 8 +-
.../oidc-relying-party-authn-beans.xml | 128 +++++----
.../oidc-relying-party-authn-flow.xml | 16 +-
.../idp/service/relying-party/postconfig.xml | 57 +++-
.../authn/oidc/rp/conf/authn/oidc-rp.properties | 3 +
...deTest.java => AddResponseTypeAndModeTest.java} | 6 +-
.../oidc/rp/impl/AuthorizationControllerTest.java | 16 +-
.../plugin/authn/oidc/rp/impl/OIDCRPFlowTest.java | 67 ++---
.../resources/conf/test-relying-party-system.xml | 3 +-
24 files changed, 794 insertions(+), 283 deletions(-)
diff --git a/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/logic/EncryptRequestObjectPredicate.java b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/logic/EncryptRequestObjectPredicate.java
new file mode 100644
index 0000000..a2577a5
--- /dev/null
+++ b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/logic/EncryptRequestObjectPredicate.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.idp.plugin.authn.oidc.rp.config.logic;
+
+import javax.annotation.Nullable;
+
+import org.opensaml.profile.context.ProfileRequestContext;
+
+import net.shibboleth.idp.profile.config.ProfileConfiguration;
+import net.shibboleth.idp.profile.context.RelyingPartyContext;
+import net.shibboleth.idp.profile.logic.AbstractRelyingPartyPredicate;
+import net.shibboleth.oidc.profile.config.OIDCAuthorizationConfiguration;
+
+/** A predicate that determines if the RequestObject JWT should be encrypted based on the profile configuration.*/
+public class EncryptRequestObjectPredicate extends AbstractRelyingPartyPredicate {
+
+ @Override
+ public boolean test(@Nullable final ProfileRequestContext input) {
+
+ final RelyingPartyContext rpc = getRelyingPartyContextLookupStrategy().apply(input);
+ if (rpc != null) {
+ final ProfileConfiguration pc = rpc.getProfileConfig();
+ if (pc instanceof OIDCAuthorizationConfiguration) {
+ return ((OIDCAuthorizationConfiguration) pc).isEncryptRequestObject(input);
+ }
+ }
+ return false;
+ }
+
+}
diff --git a/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/navigate/RequestObjectEncryptionConfigurationLookupFunction.java b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/navigate/RequestObjectEncryptionConfigurationLookupFunction.java
new file mode 100644
index 0000000..2c78b5c
--- /dev/null
+++ b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/navigate/RequestObjectEncryptionConfigurationLookupFunction.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.idp.plugin.authn.oidc.rp.config.navigate;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.annotation.Nullable;
+
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.opensaml.xmlsec.EncryptionConfiguration;
+import org.opensaml.xmlsec.SignatureSigningConfiguration;
+
+import com.nimbusds.jwt.SignedJWT;
+
+import net.shibboleth.idp.profile.config.ProfileConfiguration;
+import net.shibboleth.idp.profile.config.SecurityConfiguration;
+import net.shibboleth.idp.profile.context.RelyingPartyContext;
+import net.shibboleth.idp.profile.context.navigate.AbstractRelyingPartyLookupFunction;
+import net.shibboleth.idp.relyingparty.RelyingPartyConfigurationResolver;
+import net.shibboleth.oidc.profile.config.OIDCSecurityConfiguration;
+import net.shibboleth.oidc.security.SignatureValidationConfiguration;
+
+/**
+ * A function that returns an {@link EncryptionConfiguration} list for request object encryption by way
+ * of various lookup strategies.
+ *
+ * <p>
+ * If a specific setting is unavailable, a null value is returned.
+ * </p>
+ */
+public class RequestObjectEncryptionConfigurationLookupFunction
+ extends AbstractRelyingPartyLookupFunction<List<EncryptionConfiguration>> {
+
+ /** A resolver for default security configurations. */
+ @Nullable
+ private RelyingPartyConfigurationResolver rpResolver;
+
+ /**
+ * Set the resolver for default security configurations.
+ *
+ * @param resolver the resolver to use
+ */
+ public void setRelyingPartyConfigurationResolver(@Nullable final RelyingPartyConfigurationResolver resolver) {
+ rpResolver = resolver;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ @Nullable
+ public List<EncryptionConfiguration> apply(@Nullable final ProfileRequestContext input) {
+
+ final List<EncryptionConfiguration> configs = new ArrayList<>();
+
+ final RelyingPartyContext rpc = getRelyingPartyContextLookupStrategy().apply(input);
+ if (rpc != null) {
+ final ProfileConfiguration pc = rpc.getProfileConfig();
+ if (pc != null && pc.getSecurityConfiguration(input) instanceof OIDCSecurityConfiguration
+ && ((OIDCSecurityConfiguration) pc.getSecurityConfiguration(input))
+ .getEncryptionConfiguration() != null) {
+ configs.add(((OIDCSecurityConfiguration) pc.getSecurityConfiguration(input))
+ .getEncryptionConfiguration());
+ }
+ }
+
+ // Check for a per-profile default (relying party independent) config.
+ if (input != null && rpResolver != null) {
+ final SecurityConfiguration defaultConfig =
+ rpResolver.getDefaultSecurityConfiguration(input.getProfileId());
+ if (defaultConfig instanceof OIDCSecurityConfiguration
+ && ((OIDCSecurityConfiguration) defaultConfig)
+ .getEncryptionConfiguration() != null) {
+ configs.add(
+ ((OIDCSecurityConfiguration) defaultConfig).getEncryptionConfiguration());
+ }
+ }
+ // TODO: Support for Global Default configuration?
+ return configs;
+ }
+}
+
diff --git a/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/context/OutboundMessageHandlerContext.java b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/context/OutboundMessageHandlerContext.java
index 562c001..f39269e 100644
--- a/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/context/OutboundMessageHandlerContext.java
+++ b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/context/OutboundMessageHandlerContext.java
@@ -19,40 +19,27 @@ package net.shibboleth.idp.plugin.authn.oidc.rp.context;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
import org.opensaml.messaging.context.BaseContext;
import net.shibboleth.utilities.java.support.logic.Constraint;
/**
- * A context to stash HTTP request/response controller parameters for use by message handlers.
+ * A context to stash controller parameters for use by message handlers.
* For example, the OIDC RP preEncodeMessageHandlers.
*/
public class OutboundMessageHandlerContext extends BaseContext {
- /** The Http servlet request.*/
- @Nullable private HttpServletRequest servletRequest;
-
- /** The Http servlet response.*/
- @Nullable private HttpServletResponse servletResponse;
-
/** The spring webflow key.*/
@Nullable private String webflowKey;
/**
* Constructor.
*
- * @param request the servlet request
- * @param response the servlet response
* @param key the swf key
*/
- public OutboundMessageHandlerContext(@Nonnull final HttpServletRequest request,
- @Nonnull final HttpServletResponse response, @Nonnull final String key) {
- super();
- servletRequest = Constraint.isNotNull(request, "Http Servlet Request can not be null");
- servletResponse = Constraint.isNotNull(response, "Http Servlet Response can not be null");
+ public OutboundMessageHandlerContext(@Nonnull final String key) {
+ super();
webflowKey = Constraint.isNotNull(key, "Spring Webflow Key can not be null");
}
@@ -61,41 +48,6 @@ public class OutboundMessageHandlerContext extends BaseContext {
// Do nothing
}
- /**
- * Set the Http servlet request.
- * @param request
- */
- public void setServletRequest(@Nonnull final HttpServletRequest request) {
- servletRequest = Constraint.isNotNull(request, "Http Servlet Request can not be null");
- }
-
- /**
- * Get the Http servlet request.
- *
- * @return Returns the servletRequest.
- */
- @Nullable public HttpServletRequest getServletRequest() {
- return servletRequest;
- }
-
- /**
- * Set the Http servlet response.
- *
- * @param response the servlet response
- */
- public void setServletResponse(@Nonnull final HttpServletResponse response) {
- servletResponse = Constraint.isNotNull(response, "Http Servlet Response can not be null");
- }
-
- /**
- * Get the Http servlet response.
- *
- * @return Returns the servletResponse.
- */
- @Nullable public HttpServletResponse getServletResponse() {
- return servletResponse;
- }
-
/**
* Set the Spring Webflow execution key.
*
diff --git a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AbstractOIDCAuthenticationRequestAction.java b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AbstractOIDCAuthenticationRequestAction.java
index 9cb40ec..fd7e34d 100644
--- a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AbstractOIDCAuthenticationRequestAction.java
+++ b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AbstractOIDCAuthenticationRequestAction.java
@@ -80,9 +80,10 @@ abstract class AbstractOIDCAuthenticationRequestAction extends AbstractAuthentic
}
/**
- * Set lookup strategy for relying party context.
+ * Set the strategy used to locate the {@link RelyingPartyContext} associated with a given
+ * {@link ProfileRequestContext}.
*
- * @param strategy lookup strategy
+ * @param strategy lookup strategy
*/
public void setRelyingPartyContextLookupStrategy(
@Nonnull final Function<ProfileRequestContext,RelyingPartyContext> strategy) {
diff --git a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/PopulateACRs.java b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AddAuthenticationContextClassReferences.java
similarity index 95%
rename from idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/PopulateACRs.java
rename to idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AddAuthenticationContextClassReferences.java
index acd439c..a526704 100644
--- a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/PopulateACRs.java
+++ b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AddAuthenticationContextClassReferences.java
@@ -19,7 +19,6 @@ package net.shibboleth.idp.plugin.authn.oidc.rp.impl;
import java.security.Principal;
import java.util.List;
-import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
@@ -38,10 +37,10 @@ import net.shibboleth.oidc.authn.principal.AuthenticationContextClassReferencePr
* An action that adds any authentication context class references from the those derived from the
* profile config - which may be proxied and mapped from the upstream request.
*/
-public class PopulateACRs extends AbstractOIDCAuthenticationRequestAction {
+public class AddAuthenticationContextClassReferences extends AbstractOIDCAuthenticationRequestAction {
/** Class logger. */
- @Nonnull private final Logger log = LoggerFactory.getLogger(PopulateACRs.class);
+ @Nonnull private final Logger log = LoggerFactory.getLogger(AddAuthenticationContextClassReferences.class);
@Override
protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext,
diff --git a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/PopulateEndpointURI.java b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AddEndpointURI.java
similarity index 94%
rename from idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/PopulateEndpointURI.java
rename to idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AddEndpointURI.java
index 4929dba..eb61079 100644
--- a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/PopulateEndpointURI.java
+++ b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AddEndpointURI.java
@@ -29,10 +29,10 @@ import net.shibboleth.idp.authn.context.AuthenticationContext;
* An action that adds the authorization endpoint URI from the providers metadata
* to the under constructions authentication request.
*/
-public class PopulateEndpointURI extends AbstractOIDCAuthenticationRequestAction {
+public class AddEndpointURI extends AbstractOIDCAuthenticationRequestAction {
/** Class logger. */
- @Nonnull private final Logger log = LoggerFactory.getLogger(PopulateEndpointURI.class);
+ @Nonnull private final Logger log = LoggerFactory.getLogger(AddEndpointURI.class);
@Override
protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext,
diff --git a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/PopulateForceAuthenticationPrompt.java b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AddForceAuthenticationPrompt.java
similarity index 90%
rename from idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/PopulateForceAuthenticationPrompt.java
rename to idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AddForceAuthenticationPrompt.java
index ab75c82..d184761 100644
--- a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/PopulateForceAuthenticationPrompt.java
+++ b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AddForceAuthenticationPrompt.java
@@ -31,12 +31,13 @@ import net.shibboleth.idp.authn.AuthnEventIds;
import net.shibboleth.idp.authn.context.AuthenticationContext;
/**
- * An action that set the Prompt parameter to 'Prompt' if force authn was requested by the upstream SP.
+ * An action that sets the 'prompt' parameter to 'login' if force authn was requested by the upstream SP - is
+ * is overridden in the profile config.
*/
-public class PopulateForceAuthenticationPrompt extends AbstractOIDCAuthenticationRequestAction {
+public class AddForceAuthenticationPrompt extends AbstractOIDCAuthenticationRequestAction {
/** Class logger. */
- @Nonnull private final Logger log = LoggerFactory.getLogger(PopulateForceAuthenticationPrompt.class);
+ @Nonnull private final Logger log = LoggerFactory.getLogger(AddForceAuthenticationPrompt.class);
@Override
protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext,
diff --git a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/PopulateNonce.java b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AddNonce.java
similarity index 89%
rename from idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/PopulateNonce.java
rename to idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AddNonce.java
index 30df967..2022bde 100644
--- a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/PopulateNonce.java
+++ b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AddNonce.java
@@ -32,18 +32,19 @@ import net.shibboleth.utilities.java.support.component.ComponentSupport;
import net.shibboleth.utilities.java.support.logic.Constraint;
/**
- * An action that adds the nonce from a lookup strategy to the under constructions authentication request.
+ * An action that adds a nonce from a lookup strategy to the under constructions authentication request.
*/
-public class PopulateNonce extends AbstractOIDCAuthenticationRequestAction {
+public class AddNonce extends AbstractOIDCAuthenticationRequestAction {
/** Class logger. */
- @Nonnull private final Logger log = LoggerFactory.getLogger(PopulateNonce.class);
+ @Nonnull private final Logger log = LoggerFactory.getLogger(AddNonce.class);
/** Strategy used to generate a nonce.*/
@Nonnull private Function<ProfileRequestContext, Nonce> nonceGenerationStrategy;
/** Constructor.*/
- public PopulateNonce() {
+ public AddNonce() {
+ // Simple strategy that uses a secure random implementation to generate a nonce of length 16
nonceGenerationStrategy = prc -> new Nonce(OIDCProxySupport.generateNonce(16));
}
diff --git a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/messaging/impl/AddRedirectURI.java b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AddRedirectURI.java
similarity index 65%
rename from idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/messaging/impl/AddRedirectURI.java
rename to idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AddRedirectURI.java
index d8c7cca..84c35fb 100644
--- a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/messaging/impl/AddRedirectURI.java
+++ b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AddRedirectURI.java
@@ -1,4 +1,21 @@
-package net.shibboleth.idp.plugin.authn.oidc.rp.messaging.impl;
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.idp.plugin.authn.oidc.rp.impl;
import java.net.URI;
import java.util.function.BiFunction;
@@ -10,23 +27,23 @@ import javax.servlet.http.HttpServletRequest;
import org.opensaml.messaging.context.MessageContext;
import org.opensaml.messaging.context.navigate.RecursiveTypedParentContextLookup;
-import org.opensaml.messaging.handler.MessageHandlerException;
+import org.opensaml.profile.action.ActionSupport;
import org.opensaml.profile.context.ProfileRequestContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.nimbusds.openid.connect.sdk.claims.ClaimsSet;
-
+import net.shibboleth.idp.authn.context.AuthenticationContext;
+import net.shibboleth.oidc.profile.core.OidcEventIds;
import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
import net.shibboleth.utilities.java.support.component.ComponentSupport;
import net.shibboleth.utilities.java.support.logic.Constraint;
-/** Adds a redirect_uri to the authentication request URL and the request object claims (if present).*/
-public class AddRedirectURI extends AbstractOIDCAuthenticationRequestMessageHandler {
-
- /** The name of the redirect uri claim.*/
- private static final String REDIRECT_URI_CLAIM = "redirect_uri";
+/**
+ * Adds a redirect_uri to the authentication request
+ *
+ * TODO Events.*/
+public class AddRedirectURI extends AbstractOIDCAuthenticationRequestAction {
/** Logger. */
@Nonnull private final Logger log = LoggerFactory.getLogger(AddRedirectURI.class);
@@ -47,7 +64,7 @@ public class AddRedirectURI extends AbstractOIDCAuthenticationRequestMessageHand
*
* @param strategy the strategy.
*/
- public void setLocateProfileRequestContextStrategy(
+ public void setLocateProfileRequestContextStrategy(@Nonnull
final Function<MessageContext, ProfileRequestContext> strategy) {
ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
ComponentSupport.ifDestroyedThrowDestroyedComponentException(this);
@@ -81,31 +98,20 @@ public class AddRedirectURI extends AbstractOIDCAuthenticationRequestMessageHand
}
}
- /** {@inheritDoc} */
@Override
- protected void doInvoke(@Nonnull final MessageContext messageContext) throws MessageHandlerException {
-
- final ProfileRequestContext prc = locateProfileRequestContextStrategy.apply(messageContext);
- if (prc == null) {
- throw new MessageHandlerException(
- "Unable to locate the profile request context, redirect_uri can not be determined");
- }
-
+ protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext,
+ @Nonnull final AuthenticationContext authenticationContext) {
+
final URI redirectUri =
- redirectUriCreationStrategy.apply(getOutboundMessageContext().getServletRequest(), prc);
+ redirectUriCreationStrategy.apply(getHttpServletRequest(), profileRequestContext);
if (redirectUri == null) {
- throw new MessageHandlerException("Redirect URI could not be located or created from strategy");
+ log.error("{} Redirect URI could not be located or created from strategy", getLogPrefix());
+ ActionSupport.buildEvent(profileRequestContext, OidcEventIds.INVALID_REDIRECT_URI);
+ return;
}
log.trace("Created redirect_uri '{}'", redirectUri);
getAuthenticationRequest().setRedirectURI(redirectUri);
-
- // Also add to request object if exists
- if (getAuthenticationRequest().getRequestObjectClaimsSet() != null) {
- final ClaimsSet claims = getAuthenticationRequest().getRequestObjectClaimsSet();
- log.trace("{} Adding redirect_uri to JWT RequestObject", getLogPrefix());
- claims.setClaim(REDIRECT_URI_CLAIM, redirectUri);
- }
-
+
}
}
diff --git a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/PopulateResponseTypeAndMode.java b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AddResponseTypeAndMode.java
similarity index 74%
rename from idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/PopulateResponseTypeAndMode.java
rename to idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AddResponseTypeAndMode.java
index 232bcc6..c5e24db 100644
--- a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/PopulateResponseTypeAndMode.java
+++ b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AddResponseTypeAndMode.java
@@ -17,12 +17,9 @@
package net.shibboleth.idp.plugin.authn.oidc.rp.impl;
-import java.util.function.Function;
-
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
-import org.opensaml.messaging.context.navigate.ChildContextLookup;
import org.opensaml.profile.action.ActionSupport;
import org.opensaml.profile.action.EventIds;
import org.opensaml.profile.context.ProfileRequestContext;
@@ -34,10 +31,7 @@ import com.nimbusds.oauth2.sdk.ResponseType;
import net.shibboleth.idp.authn.context.AuthenticationContext;
import net.shibboleth.idp.profile.IdPEventIds;
-import net.shibboleth.idp.profile.context.RelyingPartyContext;
import net.shibboleth.oidc.profile.config.OIDCAuthorizationConfiguration;
-import net.shibboleth.utilities.java.support.component.ComponentSupport;
-import net.shibboleth.utilities.java.support.logic.Constraint;
/**
* Action that populates the authentication request response_mode and response_type from various stratagies,
@@ -45,44 +39,15 @@ import net.shibboleth.utilities.java.support.logic.Constraint;
*
* TODO finish
*/
-public class PopulateResponseTypeAndMode extends AbstractOIDCAuthenticationRequestAction {
+public class AddResponseTypeAndMode extends AbstractOIDCAuthenticationRequestAction {
/** The Default response type if none is selected.*/
@Nonnull private static final ResponseType DEFAULT_RESPONSE_TYPE = ResponseType.CODE;
/** Class logger. */
- @Nonnull private final Logger log = LoggerFactory.getLogger(PopulateResponseTypeAndMode.class);
-
- /**
- * Strategy used to locate the {@link RelyingPartyContext} associated with a given {@link ProfileRequestContext}.
- */
- @Nonnull private Function<ProfileRequestContext, RelyingPartyContext> relyingPartyContextLookupStrategy;
-
- /** Applicable stashed profile configuration. */
- @Nullable private OIDCAuthorizationConfiguration profileConfiguration;
+ @Nonnull private final Logger log = LoggerFactory.getLogger(AddResponseTypeAndMode.class);
- /** Constructor.*/
- public PopulateResponseTypeAndMode() {
- relyingPartyContextLookupStrategy = new ChildContextLookup<>(RelyingPartyContext.class);
- }
-
- /**
- * Set the strategy used to locate the {@link RelyingPartyContext} associated with a given
- * {@link ProfileRequestContext}.
- *
- * @param strategy lookup strategy
- */
- public void setRelyingPartyContextLookupStrategy(
- @Nonnull final Function<ProfileRequestContext,RelyingPartyContext> strategy) {
- ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
- ComponentSupport.ifDestroyedThrowDestroyedComponentException(this);
-
- relyingPartyContextLookupStrategy =
- Constraint.isNotNull(strategy, "RelyingPartyContext lookup strategy cannot be null");
- }
-
-
@Override
protected boolean doPreExecute(@Nonnull final ProfileRequestContext profileRequestContext,
@Nonnull final AuthenticationContext authenticationContext) {
@@ -97,19 +62,7 @@ public class PopulateResponseTypeAndMode extends AbstractOIDCAuthenticationReque
ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_MSG_CTX);
return false;
}
-
- final RelyingPartyContext rpCtx = relyingPartyContextLookupStrategy.apply(profileRequestContext);
- if (rpCtx != null && rpCtx.getConfiguration() != null &&
- rpCtx.getProfileConfig() instanceof OIDCAuthorizationConfiguration) {
- profileConfiguration = (OIDCAuthorizationConfiguration) rpCtx.getProfileConfig();
- }
- if (profileConfiguration == null) {
- log.error("{} Profile configuration not found", getLogPrefix());
- ActionSupport.buildEvent(profileRequestContext, IdPEventIds.INVALID_PROFILE_CONFIG);
- return false;
- }
-
-
+
return true;
}
@@ -117,7 +70,7 @@ public class PopulateResponseTypeAndMode extends AbstractOIDCAuthenticationReque
@Override protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext,
@Nonnull final AuthenticationContext authenticationContext) {
- final String responseTypeFromProfile = profileConfiguration.getResponseType(profileRequestContext);
+ final String responseTypeFromProfile = getProfileConfiguration().getResponseType(profileRequestContext);
final ResponseType responseType = parseResponseType(responseTypeFromProfile);
if (responseType == null){
log.error("{} Response_type '{}' is not supported", getLogPrefix(), responseTypeFromProfile);
@@ -125,7 +78,7 @@ public class PopulateResponseTypeAndMode extends AbstractOIDCAuthenticationReque
return;
}
- final String responseModeFromProfile = profileConfiguration.getResponseMode(profileRequestContext);
+ final String responseModeFromProfile = getProfileConfiguration().getResponseMode(profileRequestContext);
final ResponseMode responseModeOverride = parseResponseMode(responseModeFromProfile);
final ResponseMode compatibleMode = ResponseMode.resolve(null, responseType);
diff --git a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/PopulateScopes.java b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AddScopes.java
similarity index 95%
rename from idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/PopulateScopes.java
rename to idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AddScopes.java
index 07d1d82..be6231a 100644
--- a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/PopulateScopes.java
+++ b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AddScopes.java
@@ -30,10 +30,10 @@ import net.shibboleth.idp.authn.context.AuthenticationContext;
/**
* An action that adds the scopes from the profile request object to the under constructions authentication request.
*/
-public class PopulateScopes extends AbstractOIDCAuthenticationRequestAction {
+public class AddScopes extends AbstractOIDCAuthenticationRequestAction {
/** Class logger. */
- @Nonnull private final Logger log = LoggerFactory.getLogger(PopulateScopes.class);
+ @Nonnull private final Logger log = LoggerFactory.getLogger(AddScopes.class);
@Override
protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext,
diff --git a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AuthorizationController.java b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AuthorizationController.java
index 37ac136..0fbdb2a 100644
--- a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AuthorizationController.java
+++ b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AuthorizationController.java
@@ -206,10 +206,9 @@ public class AuthorizationController extends AbstractInitializableComponent {
if (nestedPRC.getOutboundMessageContext() != null &&
nestedPRC.getOutboundMessageContext().getMessage() instanceof OIDCAuthenticationRequest) {
- // Build a handler context to allow certain parameters to be set e.g. state, redirect_uri,
+ // Build a handler context to allow certain parameters to be set e.g. state,
// by the pre-message-encoders.
- final OutboundMessageHandlerContext handlerContext = new OutboundMessageHandlerContext(httpRequest,
- httpResponse, key);
+ final OutboundMessageHandlerContext handlerContext = new OutboundMessageHandlerContext(key);
nestedPRC.getOutboundMessageContext().addSubcontext(handlerContext);
diff --git a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/BuildRequestObject.java b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/BuildRequestObject.java
index 7402645..4aaa48b 100644
--- a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/BuildRequestObject.java
+++ b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/BuildRequestObject.java
@@ -56,12 +56,20 @@ public class BuildRequestObject extends AbstractOIDCAuthenticationRequestAction
/** A hook to allow additional checking of the request object claims after it is build.*/
@Nonnull private Predicate<ClaimsSet> claimsSetIsValidPredicate;
+ /**
+ * Is the request object going to be signed? if so the 'iss' and 'aud' claims will be set.
+ * Defaults to always true, as it is permissible that both 'iss' and 'aud' claim can exist in
+ * plain request objects.
+ */
+ @Nonnull private Predicate<ProfileRequestContext> requestObjectToBeSignedPredicate;
+
/** The RelyingPartyContext to operate on. */
@Nullable private RelyingPartyContext rpCtx;
/** Constructor.*/
public BuildRequestObject() {
claimsSetIsValidPredicate = Predicates.alwaysTrue();
+ requestObjectToBeSignedPredicate = Predicates.alwaysTrue();
}
/**
@@ -79,6 +87,21 @@ public class BuildRequestObject extends AbstractOIDCAuthenticationRequestAction
claimsSetIsValidPredicate = predicate;
}
}
+
+ /**
+ * Set a predicate to determine if the request object will be 'eventually' signed. If so,
+ * the 'iss' and 'aud' claims will be set into the request object.
+ *
+ * @param predicate the predicate
+ */
+ public void setRequestObjectToBeSignedPredicate(@Nullable final Predicate<ProfileRequestContext> predicate) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+ ComponentSupport.ifDestroyedThrowDestroyedComponentException(this);
+
+ if (predicate != null) {
+ requestObjectToBeSignedPredicate = predicate;
+ }
+ }
/** {@inheritDoc} */
@Override
@@ -88,28 +111,25 @@ public class BuildRequestObject extends AbstractOIDCAuthenticationRequestAction
log.debug("{} Building a plain RequestObject JWT", getLogPrefix());
final ClaimsSet requestObjectClaims = new ClaimsSet();
- //TODO check we are signing if we have selected a signing params, or if we just say must sign?
-
- requestObjectClaims.setClaim("client_id", getAuthenticationRequest().getClientID());
- requestObjectClaims.setAudience(
- new Audience(getProviderMetadataContext().getProviderInformation().getIssuer().getValue()));
- requestObjectClaims.setIssuer(new Issuer(getAuthenticationRequest().getClientID().getValue()));
+ if (requestObjectToBeSignedPredicate.test(profileRequestContext)) {
+ requestObjectClaims.setAudience(
+ new Audience(getProviderMetadataContext().getProviderInformation().getIssuer().getValue()));
+ requestObjectClaims.setIssuer(new Issuer(getAuthenticationRequest().getClientID().getValue()));
+ }
- //FIXME: replace with static claim names?
- requestObjectClaims.setClaim("nonce", getAuthenticationRequest().getNonce().getValue());
- requestObjectClaims.setClaim("response_type", getAuthenticationRequest().getResponseType());
+ requestObjectClaims.setClaim("client_id", getAuthenticationRequest().getClientID().toString());
+ requestObjectClaims.setClaim("nonce", getAuthenticationRequest().getNonce().getValue());
+ requestObjectClaims.setClaim("response_type", getAuthenticationRequest().getResponseType().toString());
// Only set the response_mode if not equal to the default for that response_type
if (!getAuthenticationRequest().getDefaultResponseMode().equals(getAuthenticationRequest().getResponseMode())){
requestObjectClaims.setClaim("response_mode", getAuthenticationRequest().getResponseMode());
}
-
- requestObjectClaims.setClaim("scope", getAuthenticationRequest().getScope());
-
- // ACRs?
+ requestObjectClaims.setClaim("redirect_uri", getAuthenticationRequest().getRedirectURI().toString());
+ requestObjectClaims.setClaim("scope", getAuthenticationRequest().getScope().toString());
// Validate the request object
- if (!validateRequestObject(requestObjectClaims)) {
+ if (!validateRequestObject(profileRequestContext, requestObjectClaims)) {
log.error("{} RequestObject claims are not valid", getLogPrefix());
ActionSupport.buildEvent(profileRequestContext, AuthnEventIds.INVALID_AUTHN_CTX);
return;
@@ -128,17 +148,19 @@ public class BuildRequestObject extends AbstractOIDCAuthenticationRequestAction
/**
* Ensure the request object is valid by assessing the claims are correct.
*
+ * @param profileRequestContext the profile request context
* @param requestObjectClaims the claims of the request object
*
* @return true if the request object claims are valid, false otherwise
*/
- private boolean validateRequestObject(final ClaimsSet requestObjectClaims) {
+ private boolean validateRequestObject(@Nonnull final ProfileRequestContext profileRequestContext,
+ @Nonnull final ClaimsSet requestObjectClaims) {
if (!claimsSetIsValidPredicate.test(requestObjectClaims)) {
return false;
}
- // TODO only if signing is enabled
- if (true) {
+
+ if (requestObjectToBeSignedPredicate.test(profileRequestContext)) {
if (requestObjectClaims.getClaim("iss") == null) {
return false;
}
diff --git a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/PopulateJWTEncryptionParameters.java b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/PopulateJWTEncryptionParameters.java
new file mode 100644
index 0000000..e8be51e
--- /dev/null
+++ b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/PopulateJWTEncryptionParameters.java
@@ -0,0 +1,294 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.idp.plugin.authn.oidc.rp.impl;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.function.Function;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.messaging.context.navigate.ChildContextLookup;
+import org.opensaml.messaging.context.navigate.RecursiveTypedParentContextLookup;
+import org.opensaml.profile.action.ActionSupport;
+import org.opensaml.profile.action.EventIds;
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.opensaml.saml.saml2.profile.context.EncryptionContext;
+import org.opensaml.xmlsec.EncryptionConfiguration;
+import org.opensaml.xmlsec.EncryptionParameters;
+import org.opensaml.xmlsec.EncryptionParametersResolver;
+import org.opensaml.xmlsec.SecurityConfigurationSupport;
+import org.opensaml.xmlsec.criterion.EncryptionConfigurationCriterion;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import net.shibboleth.idp.profile.AbstractProfileAction;
+import net.shibboleth.idp.profile.context.RelyingPartyContext;
+import net.shibboleth.oidc.metadata.context.OIDCMetadataContext;
+import net.shibboleth.oidc.metadata.context.OIDCProviderMetadataContext;
+import net.shibboleth.oidc.profile.config.OIDCAuthorizationConfiguration;
+import net.shibboleth.oidc.security.criterion.ClientInformationCriterion;
+import net.shibboleth.oidc.security.criterion.ProviderMetadataCriterion;
+import net.shibboleth.oidc.security.criterion.StaticCredentialCriterion;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
+import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.utilities.java.support.component.ComponentSupport;
+import net.shibboleth.utilities.java.support.logic.Constraint;
+import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
+import net.shibboleth.utilities.java.support.resolver.ResolverException;
+
+
+//TODO similar to PopulateOIDCEncryptionParameters? shall we merge into commons, adds the OP metadata from downstream
+// If exists, useful for proxy.
+// TODO move to commons?
+public class PopulateJWTEncryptionParameters extends AbstractProfileAction {
+
+ /** Class logger. */
+ @Nonnull private final Logger log = LoggerFactory.getLogger(PopulateJWTEncryptionParameters.class);
+
+ /** A friendly name to log as the subject of encryption parameter resolution.*/
+ @Nonnull private String forFriendlyName;
+
+ /** Strategy used to look up the {@link EncryptionContext} to store parameters in. */
+ @Nonnull private final Function<ProfileRequestContext,EncryptionContext> encryptionContextLookupStrategy;
+
+ /** Strategy used to look up a per-request {@link EncryptionConfiguration} list. */
+ @NonnullAfterInit private Function<ProfileRequestContext,List<EncryptionConfiguration>> configurationLookupStrategy;
+
+ /** Resolver for parameters to store into context. */
+ @NonnullAfterInit private EncryptionParametersResolver encParamsresolver;
+
+ /** Active configurations to feed into resolver. */
+ @Nullable @NonnullElements private List<EncryptionConfiguration> encryptionConfigurations;
+
+ /** Strategy used to look up a OIDC client metadata context. */
+ @Nullable private Function<ProfileRequestContext, OIDCMetadataContext> oidcClientMetadataContextLookupStrategy;
+
+ /** Strategy used to look up a OIDC provider metadata context. */
+ @Nullable
+ private Function<ProfileRequestContext, OIDCProviderMetadataContext> oidcProviderMetadataContextLookupStrategy;
+
+ /** Lookup function for relying party context. */
+ @Nonnull private Function<ProfileRequestContext, RelyingPartyContext> relyingPartyContextLookupStrategy;
+
+ /** Context to populate. */
+ private EncryptionContext encryptionContext;
+
+ /** Constructor. */
+ public PopulateJWTEncryptionParameters() {
+ forFriendlyName = "not-specified";
+ encryptionContextLookupStrategy = new ChildContextLookup<>(EncryptionContext.class, true);
+ oidcClientMetadataContextLookupStrategy = new ChildContextLookup<>(OIDCMetadataContext.class);
+ oidcProviderMetadataContextLookupStrategy = new ChildContextLookup<>(OIDCProviderMetadataContext.class);
+ relyingPartyContextLookupStrategy = new ChildContextLookup<>(RelyingPartyContext.class)
+ .compose(new RecursiveTypedParentContextLookup<>(ProfileRequestContext.class));
+ }
+
+ /**
+ * Set lookup strategy for relying party context.
+ *
+ * @param strategy lookup strategy
+ */
+ public void setRelyingPartyContextLookupStrategy(
+ @Nonnull final Function<ProfileRequestContext, RelyingPartyContext> strategy) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+
+ relyingPartyContextLookupStrategy =
+ Constraint.isNotNull(strategy, "RelyingPartyContext lookup strategy cannot be null");
+ }
+
+ /**
+ * Set lookup strategy for {@link OIDCMetadataContext} for input to resolution.
+ *
+ * @param strategy lookup strategy
+ */
+ public void setClientMetadataContextLookupStrategy(
+ @Nullable final Function<ProfileRequestContext, OIDCMetadataContext> strategy) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+
+ oidcClientMetadataContextLookupStrategy = strategy;
+ }
+
+ /**
+ * Set lookup strategy for {@link OIDCProviderMetadataContext} for input to resolution.
+ *
+ * @param strategy lookup strategy
+ */
+ public void setProviderMetadataContextLookupStrategy(
+ @Nullable final Function<ProfileRequestContext, OIDCProviderMetadataContext> strategy) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+
+ oidcProviderMetadataContextLookupStrategy = strategy;
+ }
+
+ /**
+ * Set the friendly name to log as the subject of encryption parameter resolution.
+ *
+ * @param name the friendly name
+ */
+ public void setForFriendlyName(@Nonnull @NotEmpty final String name) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+ ComponentSupport.ifDestroyedThrowDestroyedComponentException(this);
+
+ forFriendlyName = Constraint.isNotEmpty(name, "ForFriendlyName can not be null or empty");
+ }
+
+ /**
+ * Set the strategy used to look up a per-request {@link EncryptionConfiguration} list.
+ *
+ * @param strategy lookup strategy
+ */
+ public void setConfigurationLookupStrategy(
+ @Nonnull final Function<ProfileRequestContext, List<EncryptionConfiguration>> strategy) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+ ComponentSupport.ifDestroyedThrowDestroyedComponentException(this);
+
+ configurationLookupStrategy =
+ Constraint.isNotNull(strategy, "EncryptionConfiguration lookup strategy cannot be null");
+ }
+
+ /**
+ * Set the encParamsresolver to use for the parameters to store into the context.
+ *
+ * @param newResolver encParamsresolver to use
+ */
+ public void setEncryptionParametersResolver(@Nonnull final EncryptionParametersResolver newResolver) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+
+ encParamsresolver = Constraint.isNotNull(newResolver, "EncryptionParametersResolver cannot be null");
+ }
+
+ @Override
+ protected void doInitialize() throws ComponentInitializationException {
+ super.doInitialize();
+
+ if (encParamsresolver == null) {
+ throw new ComponentInitializationException("EncryptionParametersResolver cannot be null");
+ } else if (configurationLookupStrategy == null) {
+ configurationLookupStrategy = new Function<ProfileRequestContext, List<EncryptionConfiguration>>() {
+ @Override
+ public List<EncryptionConfiguration> apply(final ProfileRequestContext input) {
+ return Collections.singletonList(SecurityConfigurationSupport.getGlobalEncryptionConfiguration());
+ }
+ };
+ }
+ }
+
+ @Override
+ protected boolean doPreExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
+ if (!super.doPreExecute(profileRequestContext)) {
+ log.debug("{} Encryption disabled", getLogPrefix());
+ return false;
+ }
+
+ encryptionContext = encryptionContextLookupStrategy.apply(profileRequestContext);
+ if (encryptionContext == null) {
+ log.debug("{} No EncryptionContext returned by lookup strategy", getLogPrefix());
+ ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_PROFILE_CTX);
+ return false;
+ }
+ return true;
+ }
+
+
+ // Checkstyle: CyclomaticComplexity OFF
+ @Override
+ protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
+
+ log.debug("{} Resolving EncryptionParameters for {}", getLogPrefix(),forFriendlyName);
+
+ try {
+ encryptionConfigurations = configurationLookupStrategy.apply(profileRequestContext);
+ if (encryptionConfigurations == null || encryptionConfigurations.isEmpty()) {
+ throw new ResolverException("No EncryptionConfigurations returned by lookup strategy");
+ }
+ final CriteriaSet criteria = buildCriteriaSet(profileRequestContext);
+ final EncryptionParameters params = encParamsresolver.resolveSingle(criteria);
+
+ if (params != null) {
+ log.debug("{} Resolved EncryptionParameters for {}", getLogPrefix(),forFriendlyName);
+ encryptionContext.setAssertionEncryptionParameters(params);
+ } else {
+ log.warn("{} Resolver returned no EncryptionParameters", getLogPrefix());
+ ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_SEC_CFG);
+ }
+ } catch (final ResolverException e) {
+ log.error("{} Error resolving EncryptionParameters", getLogPrefix(), e);
+ ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_SEC_CFG);
+ }
+ }
+// Checkstyle: CyclomaticComplexity ON
+
+ /**
+ * Build the criteria used as input to the {@link EncryptionParametersResolver}.
+ *
+ * @param profileRequestContext current profile request context
+ *
+ * @return the criteria set to use
+ */
+ @Nonnull
+ private CriteriaSet buildCriteriaSet(@Nonnull final ProfileRequestContext profileRequestContext) {
+
+ final CriteriaSet criteria = new CriteriaSet(new EncryptionConfigurationCriterion(encryptionConfigurations));
+
+ // Add client metadata criterion
+ final OIDCMetadataContext oidcMetadataCtx =
+ oidcClientMetadataContextLookupStrategy.apply(profileRequestContext);
+ if (oidcMetadataCtx != null && oidcMetadataCtx.getClientInformation() != null) {
+ log.debug(
+ "{} Adding OIDC client information to resolution criteria for encryption algorithms",
+ getLogPrefix());
+ criteria.add(new ClientInformationCriterion(oidcMetadataCtx.getClientInformation()));
+ } else {
+ log.debug("{} No OIDC client information available", getLogPrefix());
+ }
+
+ // Add OP metadata criterion
+ final OIDCProviderMetadataContext oidcProviderMetadataCtx =
+ oidcProviderMetadataContextLookupStrategy.apply(profileRequestContext);
+ if (oidcProviderMetadataCtx != null && oidcProviderMetadataCtx.getProviderInformation() != null) {
+ log.debug("{} Adding OIDC provider information to resolution criteria for signing/digest algorithms",
+ getLogPrefix());
+ criteria.add(new ProviderMetadataCriterion(oidcProviderMetadataCtx.getProviderInformation()));
+ } else {
+ log.debug("{} OIDCProviderMetadataContext is absent", getLogPrefix());
+ }
+
+ // Add any static credentials from the RP context
+ final RelyingPartyContext rpCtx =
+ relyingPartyContextLookupStrategy.apply(profileRequestContext);
+ if (rpCtx != null && rpCtx.getConfiguration() != null &&
+ rpCtx.getProfileConfig() instanceof OIDCAuthorizationConfiguration) {
+ final OIDCAuthorizationConfiguration profileConfiguration =
+ (OIDCAuthorizationConfiguration) rpCtx.getProfileConfig();
+
+ if (profileConfiguration != null) {
+ criteria.add(
+ new StaticCredentialCriterion(profileConfiguration.getClientCredential(profileRequestContext)));
+ } else {
+ log.trace("{} Profile configuration not available, "
+ + "shared secret direct encryption credential not present", getLogPrefix());
+ }
+ }
+ return criteria;
+ }
+
+}
diff --git a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/RelyingPartyProxyEncryptionParametersResolver.java b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/RelyingPartyProxyEncryptionParametersResolver.java
new file mode 100644
index 0000000..defc219
--- /dev/null
+++ b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/RelyingPartyProxyEncryptionParametersResolver.java
@@ -0,0 +1,68 @@
+package net.shibboleth.idp.plugin.authn.oidc.rp.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Predicate;
+
+import javax.annotation.Nonnull;
+
+import org.opensaml.security.credential.Credential;
+import org.opensaml.xmlsec.EncryptionParameters;
+import org.opensaml.xmlsec.impl.BasicEncryptionParametersResolver;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.nimbusds.jose.JWSAlgorithm;
+
+import net.shibboleth.oidc.security.criterion.StaticCredentialCriterion;
+import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
+
+public class RelyingPartyProxyEncryptionParametersResolver extends BasicEncryptionParametersResolver {
+
+ /** Logger. */
+ private final Logger log = LoggerFactory.getLogger(RelyingPartyProxyEncryptionParametersResolver.class);
+
+ @Override
+ protected void resolveAndPopulateCredentialsAndAlgorithms(@Nonnull final EncryptionParameters params,
+ @Nonnull final CriteriaSet criteria, @Nonnull final Predicate<String> includeExcludePredicate) {
+
+ super.resolveAndPopulateCredentialsAndAlgorithms(params, criteria, includeExcludePredicate);
+// final List<Credential> allCredentials = new ArrayList<>();
+//
+// // Add any static credentials from the criteria
+// if (criteria.contains(StaticCredentialCriterion.class)) {
+// final Credential staticCred = criteria.get(StaticCredentialCriterion.class).getCredential();
+// log.trace("Signing credential found in criterion '{}'", staticCred.getKeyNames());
+// allCredentials.add(staticCred);
+// }
+//
+// // Add any credentials from the configuration
+// allCredentials.addAll(getEffectiveDataEncryptionCredentials(criteria));
+//
+// // Get effective signature algorithms from configuration and include/exclude predicate
+// final List<String> algorithms = getEffectiveSignatureAlgorithms(criteria, includeExcludePredicate);
+//
+// // Filter by those supported by the downstream OP
+// final List<String> filteredAlgorithms = filterForOPSupportedAlgorithms(criteria, algorithms);
+// final List<JWSAlgorithm> supportedAlgorithms = convertSupportAlgorithmsToJwkAlgorithms(filteredAlgorithms);
+// log.trace("Resolved effective signature algorithms: {}", supportedAlgorithms);
+//
+// // Pick the first credential that matches one of the supported algorithms
+// for (final Credential credential : allCredentials) {
+// log.trace("Evaluating signing credential '{}'", credential.getKeyNames());
+// final JWSAlgorithm foundSupportedAlgorithm =
+// credentialSupportsSigningAlgorithm(credential, supportedAlgorithms);
+// if (foundSupportedAlgorithm != null) {
+// log.trace("Credential supports algorithm '{}'", foundSupportedAlgorithm);
+// params.setSigningCredential(credential);
+// params.setSignatureAlgorithm(foundSupportedAlgorithm.getName());
+// return;
+// }
+// log.trace("Credential failed eval against Signing Algorithm");
+//
+// }
+ }
+
+
+
+}
diff --git a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/RelyingPartyProxySigningParametersResolver.java b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/RelyingPartyProxySigningParametersResolver.java
index 7ab808b..9b2f191 100644
--- a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/RelyingPartyProxySigningParametersResolver.java
+++ b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/RelyingPartyProxySigningParametersResolver.java
@@ -114,7 +114,7 @@ public class RelyingPartyProxySigningParametersResolver extends BasicSignatureSi
final List<String> algorithms = getEffectiveSignatureAlgorithms(criteria, includeExcludePredicate);
// Filter by those supported by the downstream OP
- final List<String> filteredAlgorithms = filterForOPSupportedAlgorithms(criteria, algorithms);
+ final List<String> filteredAlgorithms = filterForProviderSupportedAlgorithms(criteria, algorithms);
final List<JWSAlgorithm> supportedAlgorithms = convertSupportAlgorithmsToJwkAlgorithms(filteredAlgorithms);
log.trace("Resolved effective signature algorithms: {}", supportedAlgorithms);
@@ -221,7 +221,7 @@ public class RelyingPartyProxySigningParametersResolver extends BasicSignatureSi
*
* @return the current set of supported algorithms filtered by those also supported by the OP.
*/
- private List<String> filterForOPSupportedAlgorithms(
+ private List<String> filterForProviderSupportedAlgorithms(
@Nonnull final CriteriaSet criteria, @Nonnull final List<String> algorithms) {
if (criteria.contains(ProviderMetadataCriterion.class)) {
@@ -231,14 +231,14 @@ public class RelyingPartyProxySigningParametersResolver extends BasicSignatureSi
log.trace("Provider metadata supports the following signature algorithms '{}'",opSupportedAlgNames);
if (opSupportedAlgNames == null) {
- log.trace("Lookup strategy could not determine OP supported algorithms from metadata, "
+ log.trace("Lookup strategy could not determine provider supported algorithms from metadata, "
+ "no further filtering performed");
return List.copyOf(algorithms);
}
return algorithms.stream().filter(opSupportedAlgNames::contains).collect(Collectors.toList());
} else {
- log.debug("No provider metadata criterion, unable to filter for OP supported algorithms");
+ log.debug("No provider metadata criterion, unable to filter for provider supported algorithms");
return List.copyOf(algorithms);
}
}
diff --git a/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OIDCRelyingParty/oidc-relying-party-authn-beans.xml b/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OIDCRelyingParty/oidc-relying-party-authn-beans.xml
index a768faa..dcce53d 100644
--- a/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OIDCRelyingParty/oidc-relying-party-authn-beans.xml
+++ b/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OIDCRelyingParty/oidc-relying-party-authn-beans.xml
@@ -105,30 +105,38 @@
class="net.shibboleth.idp.plugin.authn.oidc.rp.impl.InitializeAuthorizationRequest" scope="prototype"
p:profileContextLookupStrategy-ref="shibboleth.ChildLookup.ProxyProfileRequestContext" />
- <bean id="PopulateResponseTypeAndMode" scope="prototype"
- class="net.shibboleth.idp.plugin.authn.oidc.rp.impl.PopulateResponseTypeAndMode"
+ <bean id="AddResponseTypeAndMode" scope="prototype"
+ class="net.shibboleth.idp.plugin.authn.oidc.rp.impl.AddResponseTypeAndMode"
p:profileContextLookupStrategy-ref="shibboleth.ChildLookup.ProxyProfileRequestContext"
p:authenticationContextLookupStrategy-ref="ParentAuthenticiationContextLookup" />
- <bean id="PopulateScopes" scope="prototype" class="net.shibboleth.idp.plugin.authn.oidc.rp.impl.PopulateScopes"
+ <bean id="AddScopes" scope="prototype" class="net.shibboleth.idp.plugin.authn.oidc.rp.impl.AddScopes"
p:profileContextLookupStrategy-ref="shibboleth.ChildLookup.ProxyProfileRequestContext"
p:authenticationContextLookupStrategy-ref="ParentAuthenticiationContextLookup" />
- <bean id="PopulateNonce" scope="prototype" class="net.shibboleth.idp.plugin.authn.oidc.rp.impl.PopulateNonce"
+ <bean id="AddNonce" scope="prototype" class="net.shibboleth.idp.plugin.authn.oidc.rp.impl.AddNonce"
p:profileContextLookupStrategy-ref="shibboleth.ChildLookup.ProxyProfileRequestContext"
p:authenticationContextLookupStrategy-ref="ParentAuthenticiationContextLookup" />
- <bean id="PopulateEndpointURI" scope="prototype"
- class="net.shibboleth.idp.plugin.authn.oidc.rp.impl.PopulateEndpointURI"
+ <bean id="AddEndpointURI" scope="prototype"
+ class="net.shibboleth.idp.plugin.authn.oidc.rp.impl.AddEndpointURI"
p:profileContextLookupStrategy-ref="shibboleth.ChildLookup.ProxyProfileRequestContext"
- p:authenticationContextLookupStrategy-ref="ParentAuthenticiationContextLookup" />
+ p:authenticationContextLookupStrategy-ref="ParentAuthenticiationContextLookup" />
+
+ <bean id="AddRedirectURI" scope="prototype"
+ class="net.shibboleth.idp.plugin.authn.oidc.rp.impl.AddRedirectURI"
+ p:profileContextLookupStrategy-ref="shibboleth.ChildLookup.ProxyProfileRequestContext"
+ p:authenticationContextLookupStrategy-ref="ParentAuthenticiationContextLookup"
+ p:httpServletRequest-ref="shibboleth.HttpServletRequest"
+ p:redirectUriCreationStrategy="#{getObject('shibboleth.oidc.rp.RedirectUriCreationStrategy') ?: getObject('shibboleth.oidc.rp.DefaultRedirectUriCreationStrategy')}" />
- <bean id="PopulateACRs" scope="prototype" class="net.shibboleth.idp.plugin.authn.oidc.rp.impl.PopulateACRs"
+ <bean id="AddAuthenticationContextClassReferences" scope="prototype"
+ class="net.shibboleth.idp.plugin.authn.oidc.rp.impl.AddAuthenticationContextClassReferences"
p:profileContextLookupStrategy-ref="shibboleth.ChildLookup.ProxyProfileRequestContext"
p:authenticationContextLookupStrategy-ref="ParentAuthenticiationContextLookup" />
- <bean id="PopulateForceAuthenticationPrompt" scope="prototype"
- class="net.shibboleth.idp.plugin.authn.oidc.rp.impl.PopulateForceAuthenticationPrompt"
+ <bean id="AddForceAuthenticationPrompt" scope="prototype"
+ class="net.shibboleth.idp.plugin.authn.oidc.rp.impl.AddForceAuthenticationPrompt"
p:profileContextLookupStrategy-ref="shibboleth.ChildLookup.ProxyProfileRequestContext"
p:authenticationContextLookupStrategy-ref="ParentAuthenticiationContextLookup" />
@@ -137,33 +145,58 @@
class="net.shibboleth.idp.plugin.authn.oidc.rp.messaging.context.logic.RequestObjectRequiredAndSupported" />
+
+ <bean id="shibboleth.authn.oidc.rp.DefaultSignRequestObjectCondition"
+ class="net.shibboleth.idp.plugin.authn.oidc.rp.config.logic.SignRequestObjectPredicate"
+ p:relyingPartyContextLookupStrategy-ref="shibboleth.ChildLookup.Proxy.RelyingPartyContext"/>
+
+ <bean id="shibboleth.authn.oidc.rp.DefaultEncryptRequestObjectCondition"
+ class="net.shibboleth.idp.plugin.authn.oidc.rp.config.logic.EncryptRequestObjectPredicate"
+ p:relyingPartyContextLookupStrategy-ref="shibboleth.ChildLookup.RelyingParty"/>
+
<bean id="PopulateRequestObjectSignatureSigningParameters"
class="net.shibboleth.oidc.security.impl.PopulateJWTSignatureSigningParameters"
c:strategy-ref="shibboleth.ChildLookup.Proxy.MessageContextLookup.Inbound"
+ p:noResultIsError="true"
p:configurationLookupStrategy-ref="RequestObjectSignatureSigningConfigurationLookup"
p:providerMetadataContextLookupStrategy-ref="shibboleth.ChildLookup.OIDCProviderMetadataContextFromOutbound"
- p:signatureSigningParametersResolver-ref="shibboleth.authn.oidc.rp.RequestObjectSignatureSigningParametersResolver">
- <property name="activationCondition">
- <bean class="net.shibboleth.idp.plugin.authn.oidc.rp.config.logic.SignRequestObjectPredicate"
- p:relyingPartyContextLookupStrategy-ref="shibboleth.ChildLookup.Proxy.RelyingPartyContext"/>
- </property>
- </bean>
+ p:signatureSigningParametersResolver-ref="shibboleth.authn.oidc.rp.RequestObjectSignatureSigningParametersResolver"
+ p:activationCondition="#{getObject('shibboleth.authn.oidc.rp.SignRequestObjectCondition') ?: getObject('shibboleth.authn.oidc.rp.DefaultSignRequestObjectCondition')}"/>
<bean id="shibboleth.authn.oidc.rp.RequestObjectSignatureSigningParametersResolver"
class="net.shibboleth.idp.plugin.authn.oidc.rp.impl.RelyingPartyProxySigningParametersResolver"
p:providerMetadataAlgorithmLookupStrategy-ref="shibboleth.authn.oidc.rp.RequestObjectSupportedSignatureSigningAlgorithms" />
- <bean id="shibboleth.authn.oidc.rp.RequestObjectSupportedSignatureSigningAlgorithms"
+ <bean id="shibboleth.authn.oidc.rp.RequestObjectSupportedSignatureSigningAlgorithms" scope="prototype"
class="net.shibboleth.idp.plugin.authn.oidc.rp.config.RequestObjectSupportedSignatureSigningAlgorithms" />
<bean id="RequestObjectSignatureSigningConfigurationLookup" lazy-init="true"
class="net.shibboleth.idp.plugin.authn.oidc.rp.config.navigate.RequestObjectSignatureSigningConfigurationLookupFunction"
p:relyingPartyConfigurationResolver-ref="shibboleth.RelyingPartyConfigurationResolver" />
+
+ <bean id="PopulateRequestObjectEncryptionParameters"
+ class="net.shibboleth.idp.plugin.authn.oidc.rp.impl.PopulateJWTEncryptionParameters" scope="prototype"
+ p:forFriendlyName="Request Object"
+ p:configurationLookupStrategy-ref="RequestObjectEncryptionConfigurationLookup"
+ p:profileContextLookupStrategy-ref="shibboleth.ChildLookup.ProxyProfileRequestContext"
+ p:providerMetadataContextLookupStrategy-ref="shibboleth.ChildLookup.OIDCProviderMetadataContextFromOutbound"
+ p:encryptionParametersResolver-ref="shibboleth.authn.oidc.rp.EncryptionParametersResolver"
+ p:activationCondition="#{getObject('shibboleth.authn.oidc.rp.EncryptRequestObjectCondition') ?: getObject('shibboleth.authn.oidc.rp.DefaultEncryptRequestObjectCondition')}"/>
+
+ <bean id="RequestObjectEncryptionConfigurationLookup" lazy-init="true"
+ class="net.shibboleth.idp.plugin.authn.oidc.rp.config.navigate.RequestObjectEncryptionConfigurationLookupFunction"
+ p:relyingPartyConfigurationResolver-ref="shibboleth.RelyingPartyConfigurationResolver" />
+
+ <bean id="shibboleth.authn.oidc.rp.EncryptionParametersResolver"
+ class="org.opensaml.xmlsec.impl.BasicEncryptionParametersResolver"/>
+
+
<bean id="BuildRequestObject" class="net.shibboleth.idp.plugin.authn.oidc.rp.impl.BuildRequestObject"
scope="prototype" p:profileContextLookupStrategy-ref="shibboleth.ChildLookup.ProxyProfileRequestContext"
p:authenticationContextLookupStrategy-ref="ParentAuthenticiationContextLookup"
- p:claimsSetIsValidPredicate="#{getObject('shibboleth.authn.oidc.rp.RequestObjectClaimsSetIsValidPredicate')}" />
+ p:claimsSetIsValidPredicate="#{getObject('shibboleth.authn.oidc.rp.RequestObjectClaimsSetIsValidPredicate')}"
+ p:requestObjectToBeSignedPredicate="#{getObject('shibboleth.authn.oidc.rp.SignRequestObjectCondition') ?: getObject('shibboleth.authn.oidc.rp.DefaultSignRequestObjectCondition')}"/>
<!-- Message Encoder factory is a prototype to allow reuse of the encoders -->
@@ -199,10 +232,6 @@
scope="prototype"
p:stateGenerationStrategy="#{getObject('shibboleth.authn.oidc.rp.StateGenerationStrategy')}" />
- <bean id="AddRedirectURI"
- class="net.shibboleth.idp.plugin.authn.oidc.rp.messaging.impl.AddRedirectURI" scope="prototype"
- p:redirectUriCreationStrategy="#{getObject('shibboleth.oidc.rp.RedirectUriCreationStrategy') ?: getObject('shibboleth.oidc.rp.DefaultRedirectUriCreationStrategy')}" />
-
<bean id="BuildPlainRequestObjectJWT"
class="net.shibboleth.idp.plugin.authn.oidc.rp.messaging.impl.BuildPlainRequestObjectJWT"
scope="prototype" />
@@ -467,6 +496,18 @@
<bean id="OIDCProviderMetadataContextChildLookup"
class="org.opensaml.messaging.context.navigate.ChildContextLookup"
c:type="#{ T(net.shibboleth.oidc.metadata.context.OIDCProviderMetadataContext) }" />
+
+ <bean id="IDTokenRequiredClaimsValidator"
+ class="net.shibboleth.oidc.security.jwt.claims.impl.RequiredClaimsValidator"
+ p:requiredClaims-ref="IDTokenRequiredOIDCClaims"/>
+
+ <util:set id="IDTokenRequiredOIDCClaims">
+ <value>iss</value>
+ <value>sub</value>
+ <value>aud</value>
+ <value>exp</value>
+ <value>iat</value>
+ </util:set>
<bean id="ExpiryClaimsValidator" class="net.shibboleth.oidc.security.jwt.claims.impl.ExpiryClaimsValidator"
p:clockSkew="%{idp.policy.clockSkew:PT1M}" />
@@ -548,6 +589,7 @@
c:type="#{ T(net.shibboleth.idp.plugin.authn.oidc.rp.context.OIDCPeerEntityContext) }" />
<util:list id="IDTokenClaimsValidators" value-type="net.shibboleth.oidc.jwt.claims.ClaimsValidator">
+ <ref bean="IDTokenRequiredClaimsValidator"/>
<ref bean="IssuerClaimsValidator" /> <!-- TODO prevent: if it contains additional audiences not trusted by the Client. -->
<ref bean="AudienceClaimsValidator" />
<ref bean="AzpClaimRequiredValidator" />
@@ -680,15 +722,8 @@
<bean id="DefaultUserInfoTokenLookupStrategy"
class="net.shibboleth.idp.plugin.authn.oidc.rp.impl.DefaultUserInfoTokenLookupStrategy" />
-
- <util:list id="UserInfoClaimsValidators" value-type="net.shibboleth.oidc.jwt.claims.ClaimsValidator">
- <ref bean="SubClaimRequiredValidator" />
- <ref bean="SubMatchesIDTokenClaimValidator" />
- <ref bean="IssuerClaimsValidator" />
- <ref bean="AudienceClaimsValidator" />
- </util:list>
-
- <bean id="SubClaimRequiredValidator"
+
+ <bean id="UserInfoTokenRequiredClaimsValidator"
class="net.shibboleth.oidc.security.jwt.claims.impl.RequiredClaimsValidator">
<property name="requiredClaims">
<list>
@@ -696,14 +731,23 @@
</list>
</property>
</bean>
-
- <bean id="SubMatchesIDTokenClaimValidator"
+
+ <bean id="SubMatchesIDTokenClaimValidator"
class="net.shibboleth.oidc.security.jwt.claims.impl.ExactMatchClaimsValidator" p:claimName="sub">
<property name="valueToMatchLookupStrategy">
<bean class="net.shibboleth.idp.plugin.authn.oidc.rp.config.navigate.SubFromIDTokenLookupFunction" />
</property>
</bean>
+ <util:list id="UserInfoClaimsValidators" value-type="net.shibboleth.oidc.jwt.claims.ClaimsValidator">
+ <ref bean="UserInfoTokenRequiredClaimsValidator" />
+ <ref bean="SubMatchesIDTokenClaimValidator" />
+ <ref bean="IssuerClaimsValidator" />
+ <ref bean="AudienceClaimsValidator" />
+ </util:list>
+
+
+
<!-- UserInfo Decryption and Signature Validation Done -->
@@ -736,22 +780,4 @@
p:transcoderRegistry-ref="shibboleth.AttributeRegistryService" />
-
-
- <!-- OLD STUFF -->
-
-
- <bean id="shibboleth.authn.oidc.rp.jwt.DefaultAuthTimeActivationCondition"
- class="net.shibboleth.oidc.security.jwt.claims.impl.ForcedAuthenticationActivationCondition" />
-
-
- <!-- These represent the default set of id_token claims which are **required** by OIDC https://openid.net/specs/openid-connect-core-1_0.html#IDToken -->
- <util:set id="shibboleth.authn.oidc.rp.DefaultRequiredOIDCClaims">
- <value>iss</value>
- <value>sub</value>
- <value>aud</value>
- <value>exp</value>
- <value>iat</value>
- </util:set>
-
</beans>
diff --git a/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OIDCRelyingParty/oidc-relying-party-authn-flow.xml b/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OIDCRelyingParty/oidc-relying-party-authn-flow.xml
index 59ccafb..99eb402 100644
--- a/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OIDCRelyingParty/oidc-relying-party-authn-flow.xml
+++ b/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OIDCRelyingParty/oidc-relying-party-authn-flow.xml
@@ -34,12 +34,13 @@
<evaluate expression="SelectProfileConfiguration" />
<evaluate expression="InitializeOAuth2ClientContext" />
<evaluate expression="InitializeAuthorizationRequest" />
- <evaluate expression="PopulateResponseTypeAndMode" />
- <evaluate expression="PopulateScopes" />
- <evaluate expression="PopulateNonce" />
- <evaluate expression="PopulateForceAuthenticationPrompt" />
- <evaluate expression="PopulateEndpointURI" />
- <evaluate expression="PopulateACRs" />
+ <evaluate expression="AddResponseTypeAndMode" />
+ <evaluate expression="AddScopes" />
+ <evaluate expression="AddNonce" />
+ <evaluate expression="AddForceAuthenticationPrompt" />
+ <evaluate expression="AddEndpointURI" />
+ <evaluate expression="AddRedirectURI"/>
+ <evaluate expression="AddAuthenticationContextClassReferences" />
<!-- <evaluate expression="PostRequestPopulateAuditContext" /> <evaluate expression="WriteAuditLog" /> -->
<!-- <evaluate expression="InitializeMessageChannelSecurityContext" /> -->
@@ -57,10 +58,11 @@
<action-state id="BuildRequestObject">
<evaluate expression="PopulateRequestObjectSignatureSigningParameters" />
+ <evaluate expression="PopulateRequestObjectEncryptionParameters" />
<evaluate expression="BuildRequestObject" />
<!-- We can not sign and encrypt the RO here, it has to be done as part of the controller so we can add state etc. -->
<evaluate expression="'proceed'" />
- <transition on="proceed" to="AuthRequest" />
+ <transition on="proceed" to="AuthnRequest" />
</action-state>
<view-state id="AuthnRequest"
diff --git a/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/service/relying-party/postconfig.xml b/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/service/relying-party/postconfig.xml
index 19bfa73..fbad510 100644
--- a/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/service/relying-party/postconfig.xml
+++ b/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/service/relying-party/postconfig.xml
@@ -35,6 +35,7 @@
p:clientCredential="#{%{idp.authn.oidc.rp.discoveryRequired:false} == true ? {null} : getObject('shibboleth.authn.oidc.rp.DefaultCredential')}"
p:tokenEndpointAuthMethods="%{idp.authn.oidc.rp.clientAuthenticationMethod:client_secret_basic}"
p:responseMode="%{idp.authn.oidc.rp.responseMode:#{null}}"
+ p:redirectUriOverride="%{idp.authn.oidc.rp.client.redirectURL:#{null}}"
p:scopes="%{idp.authn.oidc.rp.scopes:#{null}}">
<property name="forceAuthnPredicate">
<bean class="net.shibboleth.idp.saml.profile.config.logic.ProxyAwareForceAuthnPredicate" />
@@ -67,24 +68,70 @@
class="net.shibboleth.oidc.profile.config.OIDCSecurityConfiguration">
<property name="idTokenJwtDecryptionConfiguration">
<ref
- bean="#{'%{dp.authn.oidc.rp.idtoken.decrypt.config:shibboleth.authn.oidc.rp.DefaultJWTDecryptionConfiguration}'.trim()}" />
+ bean="#{'%{idp.authn.oidc.rp.idtoken.decrypt.config:shibboleth.authn.oidc.rp.DefaultJWTDecryptionConfiguration}'.trim()}" />
</property>
<property name="idTokenJwtSignatureValidationConfiguration">
<ref
- bean="#{'%{dp.authn.oidc.rp.idtoken.valid.config:shibboleth.authn.oidc.rp.DefaultJWTSignatureValidationConfiguration}'.trim()}" />
+ bean="#{'%{idp.authn.oidc.rp.idtoken.valid.config:shibboleth.authn.oidc.rp.DefaultJWTSignatureValidationConfiguration}'.trim()}" />
</property>
<!-- User info config is actually the same by default as id_token, not sure we need seperation, although could be overriden -->
<property name="userInfoJwtDecryptionConfiguration">
<ref
- bean="#{'%{dp.authn.oidc.rp.userinfotoken.decrypt.config:shibboleth.authn.oidc.rp.DefaultJWTDecryptionConfiguration}'.trim()}" />
+ bean="#{'%{idp.authn.oidc.rp.userinfotoken.decrypt.config:shibboleth.authn.oidc.rp.DefaultJWTDecryptionConfiguration}'.trim()}" />
</property>
<property name="userInfoTokenJwtSignatureValidationConfiguration">
<ref
- bean="#{'%{dp.authn.oidc.rp.userinfotoken.valid.config:shibboleth.authn.oidc.rp.DefaultJWTSignatureValidationConfiguration}'.trim()}" />
+ bean="#{'%{idp.authn.oidc.rp.userinfotoken.valid.config:shibboleth.authn.oidc.rp.DefaultJWTSignatureValidationConfiguration}'.trim()}" />
</property>
<property name="requestObjectSignatureSigningConfiguration">
<ref
- bean="#{'%{dp.authn.oidc.rp.requestobject.signing.config:shibboleth.authn.oidc.rp.DefaultRequestObjectSigningConfiguration}'.trim()}" />
+ bean="#{'%{idp.authn.oidc.rp.requestobject.signing.config:shibboleth.authn.oidc.rp.DefaultRequestObjectSigningConfiguration}'.trim()}" />
+ </property>
+ <!-- For now, Request Object encryption configuration only -->
+ <property name="encryptionConfiguration">
+ <ref bean="#{'%{idp.authn.oidc.rp.encryption.config:shibboleth.authn.oidc.rp.EncryptionConfiguration}'.trim()}" />
+ </property>
+ </bean>
+
+ <!-- Configuration for supported algorithms for Request Object encryption. -->
+ <bean id="shibboleth.authn.oidc.rp.EncryptionConfiguration" parent="shibboleth.BasicEncryptionConfiguration">
+ <property name="keyTransportEncryptionAlgorithms">
+ <list>
+ <util:constant
+ static-field="net.shibboleth.oidc.jwa.support.KeyManagementConstants.ALGO_ID_ALG_RSA_1_5" />
+ <util:constant
+ static-field="net.shibboleth.oidc.jwa.support.KeyManagementConstants.ALGO_ID_ALG_RSA_OAEP" />
+ <util:constant
+ static-field="net.shibboleth.oidc.jwa.support.KeyManagementConstants.ALGO_ID_ALG_RSA_OAEP_256" />
+ <util:constant
+ static-field="net.shibboleth.oidc.jwa.support.KeyManagementConstants.ALGO_ID_ALG_AES_128_KW" />
+ <util:constant
+ static-field="net.shibboleth.oidc.jwa.support.KeyManagementConstants.ALGO_ID_ALG_AES_192_KW" />
+ <util:constant
+ static-field="net.shibboleth.oidc.jwa.support.KeyManagementConstants.ALGO_ID_ALG_AES_256_KW" />
+ <util:constant
+ static-field="net.shibboleth.oidc.jwa.support.KeyManagementConstants.ALGO_ID_ALG_AES_128_GCM_KW" />
+ <util:constant
+ static-field="net.shibboleth.oidc.jwa.support.KeyManagementConstants.ALGO_ID_ALG_AES_192_GCM_KW" />
+ <util:constant
+ static-field="net.shibboleth.oidc.jwa.support.KeyManagementConstants.ALGO_ID_ALG_AES_256_GCM_KW" />
+ </list>
+ </property>
+ <property name="dataEncryptionAlgorithms">
+ <list>
+ <util:constant
+ static-field="net.shibboleth.oidc.jwa.support.EncryptionConstants.ALGO_ID_ENC_ALG_A128CBC_HS256" />
+ <util:constant
+ static-field="net.shibboleth.oidc.jwa.support.EncryptionConstants.ALGO_ID_ENC_ALG_A192CBC_HS384" />
+ <util:constant
+ static-field="net.shibboleth.oidc.jwa.support.EncryptionConstants.ALGO_ID_ENC_ALG_A256CBC_HS512" />
+ <util:constant
+ static-field="net.shibboleth.oidc.jwa.support.EncryptionConstants.ALGO_ID_ENC_ALG_A128GCM" />
+ <util:constant
+ static-field="net.shibboleth.oidc.jwa.support.EncryptionConstants.ALGO_ID_ENC_ALG_A192GCM" />
+ <util:constant
+ static-field="net.shibboleth.oidc.jwa.support.EncryptionConstants.ALGO_ID_ENC_ALG_A256GCM" />
+ </list>
</property>
</bean>
diff --git a/idp-oidc-rp-impl/src/main/resources/net/shibboleth/idp/plugin/authn/oidc/rp/conf/authn/oidc-rp.properties b/idp-oidc-rp-impl/src/main/resources/net/shibboleth/idp/plugin/authn/oidc/rp/conf/authn/oidc-rp.properties
index 993518c..3ac15e4 100644
--- a/idp-oidc-rp-impl/src/main/resources/net/shibboleth/idp/plugin/authn/oidc/rp/conf/authn/oidc-rp.properties
+++ b/idp-oidc-rp-impl/src/main/resources/net/shibboleth/idp/plugin/authn/oidc/rp/conf/authn/oidc-rp.properties
@@ -2,6 +2,8 @@
idp.authn.oidc.rp.proxyIssuer= <issuerId>
+idp.authn.oidc.rp.client.redirectURL= https://localhost/callback
+
# If a redirect_uri is not explicitly declared above, one can be inferred from each
# request's Host header. To avoid Host header injection attacks, the allowed origins
# must be specified here. Origins are comma seperated. Do not specify the port when
@@ -9,6 +11,7 @@ idp.authn.oidc.rp.proxyIssuer= <issuerId>
idp.authn.oidc.rp.client.redirecturl.allowedOrigins = https://localhost
+
## openid is defaulted. Other scopes could be; profile etc.
#idp.oidc.rp.scope=openid
diff --git a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/PopulateResponseTypeAndModeTest.java b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AddResponseTypeAndModeTest.java
similarity index 96%
rename from idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/PopulateResponseTypeAndModeTest.java
rename to idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AddResponseTypeAndModeTest.java
index 5e226f3..e22887a 100644
--- a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/PopulateResponseTypeAndModeTest.java
+++ b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AddResponseTypeAndModeTest.java
@@ -23,9 +23,9 @@ import net.shibboleth.oidc.profile.core.OIDCAuthenticationRequest;
import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
/** Tests for the PopulateResponseTypeAndMode action.*/
-public class PopulateResponseTypeAndModeTest extends AbstractOIDCTest {
+public class AddResponseTypeAndModeTest extends AbstractOIDCTest {
- private PopulateResponseTypeAndMode action;
+ private AddResponseTypeAndMode action;
private RelyingPartyContext rpc;
@@ -36,7 +36,7 @@ public class PopulateResponseTypeAndModeTest extends AbstractOIDCTest {
@BeforeMethod
public void setup() throws Exception {
super.setup();
- action = new PopulateResponseTypeAndMode();
+ action = new AddResponseTypeAndMode();
rpc = prc.getSubcontext(RelyingPartyContext.class, true);
oidcAuthzConfig = new OIDCAuthorizationConfiguration();
final RelyingPartyConfiguration rpConfig = new RelyingPartyConfiguration();
diff --git a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AuthorizationControllerTest.java b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AuthorizationControllerTest.java
index 98b636e..6d48544 100644
--- a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AuthorizationControllerTest.java
+++ b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AuthorizationControllerTest.java
@@ -29,7 +29,6 @@ import java.io.IOException;
import java.net.URI;
import java.net.URLEncoder;
import java.util.ArrayList;
-import java.util.Set;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -85,7 +84,6 @@ import net.shibboleth.idp.authn.impl.ExternalAuthenticationImpl;
import net.shibboleth.idp.plugin.authn.oidc.rp.context.OAuth2ClientContext;
import net.shibboleth.idp.plugin.authn.oidc.rp.context.OIDCAuthnContext;
import net.shibboleth.idp.plugin.authn.oidc.rp.context.OIDCPeerEntityContext;
-import net.shibboleth.idp.plugin.authn.oidc.rp.messaging.impl.AddRedirectURI;
import net.shibboleth.idp.plugin.authn.oidc.rp.messaging.impl.AddState;
import net.shibboleth.idp.plugin.authn.oidc.rp.messaging.impl.BuildPlainRequestObjectJWT;
import net.shibboleth.idp.plugin.authn.oidc.rp.messaging.impl.SignRequestObject;
@@ -277,10 +275,6 @@ public class AuthorizationControllerTest extends AbstractTestNGSpringContextTest
final var addState = new AddState();
addState.initialize();
- final var addRedirectUri = new AddRedirectURI();
- addRedirectUri.setRedirectUriCreationStrategy(
- new DefaultRedirectUriCreationFunction("/Authn/OIDC/RP/callback", Set.of("http://localhost")));
- addRedirectUri.initialize();
final var signer = new SignRequestObject();
signer.initialize();
final var buildRequestObjectJwt = new BuildPlainRequestObjectJWT();
@@ -288,7 +282,6 @@ public class AuthorizationControllerTest extends AbstractTestNGSpringContextTest
handlers.add(addState);
- handlers.add(addRedirectUri);
handlers.add(buildRequestObjectJwt);
handlers.add(signer);
chainingMsgHandler.setHandlers(handlers);
@@ -312,9 +305,9 @@ public class AuthorizationControllerTest extends AbstractTestNGSpringContextTest
}
/**
- * Build a nested {@link ProfileRequestContext} by configuring a suitable context tree for external authentication e.g. a
- * {@link AuthenticationContext} and {@link ExternalAuthenticationContext}. Nest the proxy PRC under the authentication
- * context.
+ * Build a nested {@link ProfileRequestContext} by configuring a suitable context tree for
+ * external authentication e.g. a {@link AuthenticationContext} and {@link ExternalAuthenticationContext}.
+ * Nest the proxy PRC under the authentication context.
*
* @return a profile request context.
* @throws Exception on error creating the duo client
@@ -454,7 +447,8 @@ public class AuthorizationControllerTest extends AbstractTestNGSpringContextTest
try {
final MessageContext messageContext = getMessageContext();
- final OIDCAuthenticationRequest outboundMessage = (OIDCAuthenticationRequest)messageContext.getMessage();
+ final OIDCAuthenticationRequest outboundMessage =
+ (OIDCAuthenticationRequest)messageContext.getMessage();
final URLBuilder urlBuilder = new URLBuilder(outboundMessage.getEndpointURI().toString());
diff --git a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/OIDCRPFlowTest.java b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/OIDCRPFlowTest.java
index 2d3f7bc..986e995 100644
--- a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/OIDCRPFlowTest.java
+++ b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/OIDCRPFlowTest.java
@@ -21,7 +21,6 @@ import java.net.InetAddress;
import java.net.URI;
import java.net.UnknownHostException;
import java.security.Principal;
-import java.time.Duration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -29,7 +28,6 @@ import java.util.Set;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
-import javax.crypto.spec.SecretKeySpec;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.TrustAllStrategy;
@@ -41,7 +39,6 @@ import org.opensaml.messaging.context.MessageContext;
import org.opensaml.profile.context.ProfileRequestContext;
import org.opensaml.security.credential.Credential;
import org.opensaml.security.credential.CredentialResolver;
-import org.opensaml.security.credential.UsageType;
import org.opensaml.xmlsec.config.GlobalAlgorithmRegistryInitializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -53,7 +50,6 @@ import org.springframework.webflow.engine.impl.FlowExecutionImpl;
import org.springframework.webflow.execution.FlowExecution;
import org.springframework.webflow.test.MockFlowBuilderContext;
-import com.nimbusds.jose.EncryptionMethod;
import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JWEAlgorithm;
import com.nimbusds.jose.jwk.RSAKey;
@@ -86,16 +82,12 @@ import net.shibboleth.oidc.metadata.context.OIDCProviderMetadataContext;
import net.shibboleth.oidc.profile.config.OIDCAuthorizationConfiguration;
import net.shibboleth.oidc.profile.config.OIDCSecurityConfiguration;
import net.shibboleth.oidc.profile.core.OIDCAuthenticationRequest;
-import net.shibboleth.oidc.security.credential.BasicExpiringJWKCredential;
import net.shibboleth.oidc.security.credential.BasicJWKCredential;
-import net.shibboleth.oidc.security.credential.JWKCredential;
import net.shibboleth.oidc.security.credential.impl.BasicJOSEObjectCredentialResolver;
-import net.shibboleth.oidc.security.credential.impl.JWKEncryptionCredentialContext;
import net.shibboleth.oidc.security.impl.BasicJWTDecryptionConfiguration;
import net.shibboleth.oidc.security.impl.BasicSignatureValidationConfiguration;
import net.shibboleth.oidc.security.impl.CriterionCredentialResolver;
import net.shibboleth.oidc.security.impl.ExplicitKeySignedJWTTrustEngine;
-import net.shibboleth.oidc.security.impl.JWSAssemblyUtils;
import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
import net.shibboleth.utilities.java.support.annotation.constraint.Unmodifiable;
@@ -107,7 +99,15 @@ import okhttp3.mockwebserver.MockWebServer;
import okhttp3.tls.HandshakeCertificates;
import okhttp3.tls.HeldCertificate;
-/** Test the OIDC relying party flow.*/
+/**
+ *
+ * Test the OIDC relying party flow.
+ *
+ * <p>Any test which tests flow execution up to the authentication request controller will use config
+ * in the various XML configuration files. Any test which tests flow execution from the authentication
+ * request controller will need to setup all required contexts programatically. </p>
+ *
+ * */
public class OIDCRPFlowTest extends AbstractAuthnXmlFlowExecutionTests {
private static final String OP_ISSUER_ID = "https://localhost:9918";
@@ -117,6 +117,8 @@ public class OIDCRPFlowTest extends AbstractAuthnXmlFlowExecutionTests {
private final String RP_ALLOWED_ORIGINS = "https://localhost";
+ private static final String REDIRECT_URI_OVERRIDE = "https://localhost/callback";
+
private static final String CLIENT_ID = "demo_rp";
private static final String CLIENT_SECRET = "Xp2s5v8y/B?E(H+MbQeThWmYq3t6w9z$";
@@ -291,6 +293,8 @@ public class OIDCRPFlowTest extends AbstractAuthnXmlFlowExecutionTests {
/** Path to the flow to be tested.*/
@Nonnull private static final String FLOW =
"/META-INF/net/shibboleth/idp/flows/authn/OIDCRelyingParty/oidc-relying-party-authn-flow.xml";
+
+
/** Class logger. */
@Nonnull private final Logger log = LoggerFactory.getLogger(OIDCRPFlowTest.class);
@@ -354,6 +358,10 @@ public class OIDCRPFlowTest extends AbstractAuthnXmlFlowExecutionTests {
addBeanDefinition(builderContext, "shibboleth.BasicSignatureSigningConfiguration",BeanDefinitionBuilder.
genericBeanDefinition(org.opensaml.xmlsec.impl.BasicSignatureSigningConfiguration.class)
+ .setAbstract(true).getBeanDefinition());
+
+ addBeanDefinition(builderContext, "shibboleth.BasicEncryptionConfiguration",BeanDefinitionBuilder.
+ genericBeanDefinition(org.opensaml.xmlsec.impl.BasicEncryptionConfiguration.class)
.setAbstract(true).getBeanDefinition());
try {
@@ -378,12 +386,14 @@ public class OIDCRPFlowTest extends AbstractAuthnXmlFlowExecutionTests {
loadBeanDefinitionsFromXmlFile(builderContext,
new ClassPathResource("META-INF/net.shibboleth.idp/postconfig.xml"),
- Map.of("idp.authn.oidc.rp.client.clientId", CLIENT_ID,
- "idp.authn.oidc.rp.client.clientSecret",CLIENT_SECRET));
+ null);
+ // Note, is the relying-party which loads the profile config in the postconfig.
+ // So properties for the profile config need to go here.
loadBeanDefinitionsFromXmlFile(builderContext,
new ClassPathResource("conf/test-relyingparty-resolver-service.xml"),
Map.of("idp.authn.oidc.rp.client.clientId", CLIENT_ID,
+ "idp.authn.oidc.rp.client.redirectURL", REDIRECT_URI_OVERRIDE,
"idp.authn.oidc.rp.client.clientSecret",CLIENT_SECRET));
loadBeanDefinitionsFromXmlFile(builderContext,
@@ -493,8 +503,7 @@ public class OIDCRPFlowTest extends AbstractAuthnXmlFlowExecutionTests {
final Map<String,String> mockProperties = Map.of(
"idp.service.clientinfo.failFast","false",
"idp.entityID", "http://idp.example.com/",
- "idp.authn.oidc.rp.proxyIssuer",OP_ISSUER_ID,
- "idp.oidc.rp.redirecturl.allowedOrigins", RP_ALLOWED_ORIGINS);
+ "idp.authn.oidc.rp.proxyIssuer",OP_ISSUER_ID);
setMockProperties(mockProperties);
@@ -532,8 +541,7 @@ public class OIDCRPFlowTest extends AbstractAuthnXmlFlowExecutionTests {
final Map<String,String> mockProperties = Map.of(
"idp.service.clientinfo.failFast","false",
"idp.entityID", "http://idp.example.com/",
- "idp.authn.oidc.rp.proxyIssuer",OP_ISSUER_ID_REQUESTOBJECT_TRUE,
- "idp.oidc.rp.redirecturl.allowedOrigins", RP_ALLOWED_ORIGINS);
+ "idp.authn.oidc.rp.proxyIssuer",OP_ISSUER_ID_REQUESTOBJECT_TRUE);
setMockProperties(mockProperties);
@@ -566,8 +574,7 @@ public class OIDCRPFlowTest extends AbstractAuthnXmlFlowExecutionTests {
final Map<String,String> mockProperties = Map.of(
"idp.service.clientinfo.failFast","false",
"idp.entityID", "http://idp.example.com/",
- "idp.authn.oidc.rp.proxyIssuer",OP_ISSUER_ID,
- "idp.oidc.rp.redirecturl.allowedOrigins", RP_ALLOWED_ORIGINS);
+ "idp.authn.oidc.rp.proxyIssuer",OP_ISSUER_ID);
setMockProperties(mockProperties);
@@ -661,10 +668,9 @@ public class OIDCRPFlowTest extends AbstractAuthnXmlFlowExecutionTests {
setFlowModelResources(flowResources);
setSubflows(subflows);
- final Map<String,String> mockProperties = Map.of(
+ final Map<String,String> mockProperties = Map.of(
"idp.entityID", "http://idp.example.com/",
- "idp.authn.oidc.rp.proxyIssuer",OP_ISSUER_ID,
- "idp.oidc.rp.redirecturl.allowedOrigins", RP_ALLOWED_ORIGINS);
+ "idp.authn.oidc.rp.proxyIssuer",OP_ISSUER_ID);
setMockProperties(mockProperties);
@@ -713,10 +719,9 @@ public class OIDCRPFlowTest extends AbstractAuthnXmlFlowExecutionTests {
setFlowModelResources(flowResources);
setSubflows(subflows);
- final Map<String,String> mockProperties = Map.of(
+ final Map<String,String> mockProperties = Map.of(
"idp.entityID", "http://idp.example.com/",
- "idp.authn.oidc.rp.proxyIssuer",OP_ISSUER_ID,
- "idp.oidc.rp.redirecturl.allowedOrigins", RP_ALLOWED_ORIGINS);
+ "idp.authn.oidc.rp.proxyIssuer",OP_ISSUER_ID);
setMockProperties(mockProperties);
@@ -765,8 +770,7 @@ public class OIDCRPFlowTest extends AbstractAuthnXmlFlowExecutionTests {
final Map<String,String> mockProperties = Map.of(
"idp.service.clientinfo.failFast","false",
- "idp.entityID", "http://idp.example.com/",
- "idp.authn.oidc.rp.proxyIssuer",OP_ISSUER_ID);
+ "idp.entityID", "http://idp.example.com/");
setMockProperties(mockProperties);
@@ -814,8 +818,7 @@ public class OIDCRPFlowTest extends AbstractAuthnXmlFlowExecutionTests {
final Map<String,String> mockProperties = Map.of(
"idp.service.clientinfo.failFast","false",
"idp.entityID", "http://idp.example.com/",
- "idp.authn.oidc.rp.proxyIssuer",OP_ISSUER_ID,
- "idp.oidc.rp.redirecturl.allowedOrigins", RP_ALLOWED_ORIGINS);
+ "idp.authn.oidc.rp.proxyIssuer",OP_ISSUER_ID);
setMockProperties(mockProperties);
@@ -946,8 +949,7 @@ public class OIDCRPFlowTest extends AbstractAuthnXmlFlowExecutionTests {
final Map<String,String> mockProperties = Map.of(
"idp.service.clientinfo.failFast","false",
"idp.entityID", "http://idp.example.com/",
- "idp.authn.oidc.rp.proxyIssuer",OP_ISSUER_ID,
- "idp.oidc.rp.redirecturl.allowedOrigins", RP_ALLOWED_ORIGINS);
+ "idp.authn.oidc.rp.proxyIssuer",OP_ISSUER_ID);
setMockProperties(mockProperties);
@@ -1041,8 +1043,7 @@ public class OIDCRPFlowTest extends AbstractAuthnXmlFlowExecutionTests {
final Map<String,String> mockProperties = Map.of(
"idp.service.clientinfo.failFast","false",
"idp.entityID", "http://idp.example.com/",
- "idp.authn.oidc.rp.proxyIssuer",OP_ISSUER_ID,
- "idp.oidc.rp.redirecturl.allowedOrigins", RP_ALLOWED_ORIGINS);
+ "idp.authn.oidc.rp.proxyIssuer",OP_ISSUER_ID);
setMockProperties(mockProperties);
@@ -1098,6 +1099,7 @@ public class OIDCRPFlowTest extends AbstractAuthnXmlFlowExecutionTests {
partyConfig.setClientCredential(TestCredentialHelper.createClientSecretCredential(CLIENT_SECRET));
partyConfig.setTokenEndpointAuthMethods(Set.of("client_secret_basic"));
partyConfig.setClientId(CLIENT_ID);
+ partyConfig.setRedirectUriOverride(REDIRECT_URI_OVERRIDE);
final RelyingPartyConfiguration rPartyConfig = new RelyingPartyConfiguration();
rPartyConfig.setResponderId("http://idp.example.com/");
partyContext.setConfiguration(rPartyConfig);
@@ -1143,8 +1145,7 @@ public class OIDCRPFlowTest extends AbstractAuthnXmlFlowExecutionTests {
final Map<String,String> mockProperties = Map.of(
"idp.service.clientinfo.failFast","false",
"idp.entityID", "http://idp.example.com/",
- "idp.authn.oidc.rp.proxyIssuer",OP_ISSUER_ID,
- "idp.oidc.rp.redirecturl.allowedOrigins", RP_ALLOWED_ORIGINS);
+ "idp.authn.oidc.rp.proxyIssuer",OP_ISSUER_ID);
setMockProperties(mockProperties);
diff --git a/idp-oidc-rp-impl/src/test/resources/conf/test-relying-party-system.xml b/idp-oidc-rp-impl/src/test/resources/conf/test-relying-party-system.xml
index 4cb7807..877092d 100644
--- a/idp-oidc-rp-impl/src/test/resources/conf/test-relying-party-system.xml
+++ b/idp-oidc-rp-impl/src/test/resources/conf/test-relying-party-system.xml
@@ -53,7 +53,8 @@
<bean id="TestRequestObject" parent="RelyingPartyByName" c:relyingPartyIds="https://localhost:9919">
<property name="profileConfigurations">
<list>
- <bean parent="OIDC.SSO" p:useRequestObject="true" p:signRequestObject="true"/>
+ <bean parent="OIDC.SSO" p:useRequestObject="true" p:signRequestObject="true"
+ p:encryptRequestObject="false"/>
</list>
</property>
</bean>
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list