[java-idp-plugin-oidc-rp] branch main updated: Add individual requested claims action
Phil Smart
philip.smart at jisc.ac.uk
Thu Jul 21 13:11:40 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=f5d15a0453165588ed1194a2fa2fcca57e1c38eb
The following commit(s) were added to refs/heads/main by this push:
new f5d15a0 Add individual requested claims action
f5d15a0 is described below
commit f5d15a0453165588ed1194a2fa2fcca57e1c38eb
Author: Phil Smart <philip.smart at jisc.ac.uk>
AuthorDate: Thu Jul 21 14:11:35 2022 +0100
Add individual requested claims action
Is just a hook for extension
---
.../authn/oidc/rp/impl/AddRequestedClaims.java | 101 ++++++++++++++++
.../authn/oidc/rp/impl/BuildRequestObject.java | 24 ++--
.../idp/plugin/authn/oidc/rp/impl/DecryptJWT.java | 21 ++++
.../oidc-relying-party-authn-beans.xml | 26 ++++-
.../oidc-relying-party-authn-flow.xml | 1 +
.../resources/templates/oidc-request-form-post.vm | 4 +-
.../authn/oidc/rp/impl/AbstractOIDCTest.java | 14 ++-
.../authn/oidc/rp/impl/AddRequestedClaimsTest.java | 107 +++++++++++++++++
.../oidc/rp/impl/AuthorizationControllerTest.java | 2 -
.../authn/oidc/rp/impl/BuildRequestObjectTest.java | 130 +++++++++++++++++++++
.../flow/AbstractAuthnXmlFlowExecutionTests.java | 6 +-
.../test-provider-requestobject-encrypt.json | 1 +
12 files changed, 417 insertions(+), 20 deletions(-)
diff --git a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AddRequestedClaims.java b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AddRequestedClaims.java
new file mode 100644
index 0000000..855edcd
--- /dev/null
+++ b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AddRequestedClaims.java
@@ -0,0 +1,101 @@
+/*
+ * 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.function.Function;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.nimbusds.openid.connect.sdk.OIDCClaimsRequest;
+
+import net.shibboleth.idp.authn.context.AuthenticationContext;
+import net.shibboleth.utilities.java.support.component.ComponentSupport;
+import net.shibboleth.utilities.java.support.logic.FunctionSupport;
+
+/**
+ * An action that adds requested claims to the under constructions authentication request.
+ *
+ * <p>The claims are added from a customizable strategy/hook. No additional claims are provided by default.</p>
+ */
+public class AddRequestedClaims extends AbstractOIDCAuthenticationRequestAction {
+
+ /** Class logger. */
+ @Nonnull private final Logger log = LoggerFactory.getLogger(AddRequestedClaims.class);
+
+ /** A hook that creates requested claims JSON Object from the profile request object.*/
+ @Nonnull private Function<ProfileRequestContext, OIDCClaimsRequest> requestedClaimsHook;
+
+ /** Constructor.*/
+ public AddRequestedClaims() {
+ requestedClaimsHook = FunctionSupport.constant(null);
+ }
+
+ /**
+ * Set the hook that generates a requested claims JSON Object from the given profile request object.
+ *
+ * @param hook the hook
+ */
+ public void setRequestedClaimsHook(@Nullable final Function<ProfileRequestContext, OIDCClaimsRequest> hook) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+ ComponentSupport.ifDestroyedThrowDestroyedComponentException(this);
+
+ if (hook != null) {
+ requestedClaimsHook = hook;
+ }
+ }
+
+ @Override
+ protected boolean doPreExecute(final ProfileRequestContext profileRequestContext,
+ final AuthenticationContext authenticationContext) {
+
+ if (!super.doPreExecute(profileRequestContext, authenticationContext)) {
+ return false;
+ }
+
+ if (!getProviderMetadata().supportsClaimsParam()) {
+ log.trace("{} Downstream OpenID Provider does not support the 'claims' parameter", getLogPrefix());
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext,
+ @Nonnull final AuthenticationContext authenticationContext) {
+
+ final OIDCClaimsRequest requestedClaims = requestedClaimsHook.apply(profileRequestContext);
+ if (requestedClaims != null) {
+ getAuthenticationRequest().setRequestedClaims(requestedClaims);
+ log.trace("{} Added requested claims '{}' to the authentication request for client '{}'",getLogPrefix(),
+ requestedClaims, getAuthenticationRequest().getClientID());
+ } else {
+ log.trace("{} No individual 'claims' requested claims", getLogPrefix());
+ }
+
+
+ }
+
+
+
+}
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 1e3f666..bb77907 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
@@ -109,6 +109,8 @@ public class BuildRequestObject extends AbstractOIDCAuthenticationRequestAction
@Nonnull final AuthenticationContext authenticationContext) {
log.debug("{} Building a plain RequestObject JWT", getLogPrefix());
+
+ final OIDCAuthenticationRequest authnRequest = getAuthenticationRequest();
final ClaimsSet requestObjectClaims = new ClaimsSet();
if (requestObjectToBeSignedPredicate.test(profileRequestContext)) {
@@ -122,19 +124,23 @@ public class BuildRequestObject extends AbstractOIDCAuthenticationRequestAction
ActionSupport.buildEvent(profileRequestContext, AuthnEventIds.INVALID_AUTHN_CTX);
return;
}
- requestObjectClaims.setIssuer(new Issuer(getAuthenticationRequest().getClientID().getValue()));
+ requestObjectClaims.setIssuer(new Issuer(authnRequest.getClientID().getValue()));
}
-
+ //TODO lots of possible NPEs here?
requestObjectClaims.setClaim("client_id", getAuthenticationRequest().getClientID().toString());
- requestObjectClaims.setClaim("nonce", getAuthenticationRequest().getNonce().getValue());
- requestObjectClaims.setClaim("response_type", getAuthenticationRequest().getResponseType().toString());
+ requestObjectClaims.setClaim("nonce", authnRequest.getNonce().getValue());
+ requestObjectClaims.setClaim("response_type", authnRequest.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());
+ if (!authnRequest.getDefaultResponseMode().equals(authnRequest.getResponseMode())){
+ requestObjectClaims.setClaim("response_mode", authnRequest.getResponseMode());
+ }
+ requestObjectClaims.setClaim("redirect_uri", authnRequest.getRedirectURI().toString());
+ requestObjectClaims.setClaim("scope", authnRequest.getScope().toString());
+
+ if (authnRequest.getRequestedClaims() != null) {
+ requestObjectClaims.setClaim("claims", authnRequest.getRequestedClaims());
}
- requestObjectClaims.setClaim("redirect_uri", getAuthenticationRequest().getRedirectURI().toString());
- requestObjectClaims.setClaim("scope", getAuthenticationRequest().getScope().toString());
// Validate the request object
if (!validateRequestObject(profileRequestContext, requestObjectClaims)) {
@@ -149,7 +155,7 @@ public class BuildRequestObject extends AbstractOIDCAuthenticationRequestAction
}
// Create a plain JWT at first, can be signed and encrypted later
- getAuthenticationRequest().setRequestObjectClaimsSet(requestObjectClaims);
+ authnRequest.setRequestObjectClaimsSet(requestObjectClaims);
}
diff --git a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/DecryptJWT.java b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/DecryptJWT.java
index aae31b5..e4b1319 100644
--- a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/DecryptJWT.java
+++ b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/DecryptJWT.java
@@ -17,6 +17,7 @@
package net.shibboleth.idp.plugin.authn.oidc.rp.impl;
+import java.text.ParseException;
import java.util.function.BiConsumer;
import java.util.function.Function;
@@ -32,6 +33,8 @@ import org.opensaml.xmlsec.encryption.support.DecryptionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.nimbusds.jose.JWEObject;
+import com.nimbusds.jose.JWEObject.State;
import com.nimbusds.jwt.EncryptedJWT;
import com.nimbusds.jwt.JWT;
@@ -41,6 +44,8 @@ import net.shibboleth.oidc.security.JWTDecryptionParameters;
import net.shibboleth.oidc.security.context.JWTSecurityParametersContext;
import net.shibboleth.oidc.security.impl.JWTDecrypter;
import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
+import net.shibboleth.utilities.java.support.codec.Base64Support;
+import net.shibboleth.utilities.java.support.codec.DecodingException;
import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
import net.shibboleth.utilities.java.support.component.ComponentSupport;
import net.shibboleth.utilities.java.support.logic.Constraint;
@@ -165,6 +170,9 @@ public class DecryptJWT extends AbstractProfileAction {
try {
final JWT decryptedJWT = decrypter.decrypt(encryptedJwt);
log.debug("{} JWT decrypted successfully", getLogPrefix());
+ if (log.isTraceEnabled()) {
+ logJWT(decryptedJWT);
+ }
jwtUpdateStrategy.accept(profileRequestContext, decryptedJWT);
} catch (final DecryptionException e) {
log.error("{} Unable to decrypt JWT", getLogPrefix(), e);
@@ -172,5 +180,18 @@ public class DecryptJWT extends AbstractProfileAction {
return;
}
}
+
+ /**
+ * Log (on trace) the JWT.
+ *
+ * @param jwt the JWT to log.
+ */
+ private void logJWT(@Nonnull final JWT jwt) {
+ try {
+ log.trace("{} Decrypted JWT: {}", getLogPrefix(), jwt.getJWTClaimsSet().toString());
+ } catch (final IllegalStateException | ParseException e) {
+ log.trace("{} Unable to print decrypted JWT: {}", getLogPrefix(), e.getMessage());
+ }
+ }
}
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 4fa23fa..e82f0e6 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
@@ -121,8 +121,32 @@
<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="AddRequestedClaims" scope="prototype"
+ class="net.shibboleth.idp.plugin.authn.oidc.rp.impl.AddRequestedClaims"
+ p:profileContextLookupStrategy-ref="shibboleth.ChildLookup.ProxyProfileRequestContext"
+ p:authenticationContextLookupStrategy-ref="ParentAuthenticiationContextLookup"
+ p:requestedClaimsHook="#{getObject('shibboleth.oidc.rp.RequestedClaimsHook')}" />
+
+ <!-- TEST request claims hook -->
+ <bean id="shibboleth.oidc.rp.RequestedClaimsHook" parent="shibboleth.Functions.Scripted"
+ factory-method="inlineScript"
+ p:inputType="org.opensaml.profile.context.ProfileRequestContext"
+ p:outputType="com.nimbusds.openid.connect.sdk.OIDCClaimsRequest">
+ <constructor-arg>
+ <value>
+ <![CDATA[
+ var requestedClaims = new com.nimbusds.openid.connect.sdk.OIDCClaimsRequest()
+ .withIDTokenClaimsRequest(new com.nimbusds.openid.connect.sdk.assurance.claims.VerifiedClaimsSetRequest().add("given_name"))
+ .withUserInfoClaimsRequest(new com.nimbusds.openid.connect.sdk.assurance.claims.VerifiedClaimsSetRequest().add("family_name"))
+ requestedClaims;
+ ]]>
+ </value>
+ </constructor-arg>
+
+ </bean>
+
<bean id="AddRedirectURI" scope="prototype"
class="net.shibboleth.idp.plugin.authn.oidc.rp.impl.AddRedirectURI"
p:profileContextLookupStrategy-ref="shibboleth.ChildLookup.ProxyProfileRequestContext"
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 9354e25..a43ae1d 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
@@ -39,6 +39,7 @@
<evaluate expression="AddNonce" />
<evaluate expression="AddForceAuthenticationPrompt" />
<evaluate expression="AddEndpointURI" />
+ <evaluate expression="AddRequestedClaims" />
<evaluate expression="AddRedirectURI"/>
<evaluate expression="AddAuthenticationContextClassReferences" />
<!-- <evaluate expression="PostRequestPopulateAuditContext" /> <evaluate expression="WriteAuditLog" /> -->
diff --git a/idp-oidc-rp-impl/src/main/resources/templates/oidc-request-form-post.vm b/idp-oidc-rp-impl/src/main/resources/templates/oidc-request-form-post.vm
index e8381a2..8afcbfd 100644
--- a/idp-oidc-rp-impl/src/main/resources/templates/oidc-request-form-post.vm
+++ b/idp-oidc-rp-impl/src/main/resources/templates/oidc-request-form-post.vm
@@ -32,8 +32,10 @@
<input type="hidden" name="state" value="${state}" />#end #if($prompt)
<input type="hidden" name="prompt" value="${prompt}" />#end #if($request)
+
+ <input type="hidden" name="request" value="${request}" />#end #if($claims)
- <input type="hidden" name="request" value="${request}" />#end #if($nonce)
+ <input type="hidden" name="claims" value="${claims}" />#end #if($nonce)
<input type="hidden" name="nonce" value="${nonce}" />#end
</div>
diff --git a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AbstractOIDCTest.java b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AbstractOIDCTest.java
index 69e084d..44c8db9 100644
--- a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AbstractOIDCTest.java
+++ b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AbstractOIDCTest.java
@@ -140,6 +140,9 @@ public abstract class AbstractOIDCTest {
/** The request context to use.*/
protected OIDCPeerEntityContext peerEntityCtx;
+ /** The authentication request.*/
+ protected OIDCAuthenticationRequest authnRequest;
+
/**
* Setup the various contexts.
*
@@ -158,10 +161,10 @@ public abstract class AbstractOIDCTest {
ac.addSubcontext(prc);
final MessageContext outMsgCtx = new MessageContext();
- final OIDCAuthenticationRequest request = new OIDCAuthenticationRequest(new ClientID("https://rp.example.com"));
- request.setState(new State("8df98fd63a53fa5b5433d6f8754bca5d.65317332"));
- request.setRedirectURI(new URI("https://rp.example.com/callback"));
- outMsgCtx.setMessage(request);
+ authnRequest = new OIDCAuthenticationRequest(new ClientID("https://rp.example.com"));
+ authnRequest.setState(new State("8df98fd63a53fa5b5433d6f8754bca5d.65317332"));
+ authnRequest.setRedirectURI(new URI("https://rp.example.com/callback"));
+ outMsgCtx.setMessage(authnRequest);
prc.setOutboundMessageContext(outMsgCtx);
// FIXME we should no longer need this context
@@ -180,8 +183,7 @@ public abstract class AbstractOIDCTest {
peerEntityCtx.addSubcontext(providerCtx);
outMsgCtx.addSubcontext(peerEntityCtx);
- //Set the inbound reponse.
-
+ //Set the inbound reponse.
final MessageContext inMsgCtx = new MessageContext();
inMsgCtx.setMessage(AuthenticationResponseParser.parse(
new URI("/idp/profile/Authn/OIDC/RP/callback"
diff --git a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AddRequestedClaimsTest.java b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AddRequestedClaimsTest.java
new file mode 100644
index 0000000..b0814c9
--- /dev/null
+++ b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AddRequestedClaimsTest.java
@@ -0,0 +1,107 @@
+/*
+ * 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 static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import org.opensaml.messaging.context.navigate.ChildContextLookup;
+import org.opensaml.messaging.context.navigate.ParentContextLookup;
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.springframework.webflow.execution.Event;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.nimbusds.openid.connect.sdk.OIDCClaimsRequest;
+import com.nimbusds.openid.connect.sdk.assurance.claims.VerifiedClaimsSetRequest;
+
+import net.shibboleth.idp.authn.context.AuthenticationContext;
+import net.shibboleth.idp.profile.context.RelyingPartyContext;
+import net.shibboleth.idp.profile.context.navigate.WebflowRequestContextProfileRequestContextLookup;
+import net.shibboleth.idp.relyingparty.RelyingPartyConfiguration;
+import net.shibboleth.oidc.profile.config.OIDCAuthorizationConfiguration;
+import net.shibboleth.oidc.profile.core.OIDCAuthenticationRequest;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+
+/** Tests for the AddRequestedClaims action.*/
+public class AddRequestedClaimsTest extends AbstractOIDCTest {
+
+ /** The action to test.*/
+ private AddRequestedClaims action;
+
+ /** The RPC.*/
+ private RelyingPartyContext rpc;
+
+ /** The profile config.*/
+ private OIDCAuthorizationConfiguration oidcAuthzConfig;
+
+ @Override
+ @BeforeMethod
+ public void setup() throws Exception {
+ super.setup();
+ action = new AddRequestedClaims();
+
+ rpc = prc.getSubcontext(RelyingPartyContext.class, true);
+ oidcAuthzConfig = new OIDCAuthorizationConfiguration();
+ final RelyingPartyConfiguration rpConfig = new RelyingPartyConfiguration();
+ rpc.setProfileConfig(oidcAuthzConfig);
+ rpc.setConfiguration(rpConfig);
+
+ action.setProfileContextLookupStrategy(new ChildContextLookup<>(ProfileRequestContext.class).compose(
+ new ChildContextLookup<>(AuthenticationContext.class)
+ .compose(new WebflowRequestContextProfileRequestContextLookup())));
+
+ action.setAuthenticationContextLookupStrategy(new ParentContextLookup<>(AuthenticationContext.class));
+ }
+
+ @Test
+ public void testAddRequestedClaims() throws ComponentInitializationException {
+
+ action.setRequestedClaimsHook(prc -> {
+ final OIDCClaimsRequest claims = new OIDCClaimsRequest()
+ .withIDTokenClaimsRequest(new VerifiedClaimsSetRequest().add("given_name"))
+ .withUserInfoClaimsRequest(new VerifiedClaimsSetRequest().add("family_name"));
+ return claims;
+ });
+
+ action.initialize();
+
+ final Event event = action.execute(src);
+ assertNull(event);
+ assertNotNull(prc.getOutboundMessageContext().getMessage());
+ assertNotNull(((OIDCAuthenticationRequest)prc.getOutboundMessageContext()
+ .getMessage()).getRequestedClaims());
+ assertNotNull(((OIDCAuthenticationRequest)prc.getOutboundMessageContext()
+ .getMessage()).getRequestedClaims().getIDTokenClaimsRequest().get("given_name", null));
+ assertNotNull(((OIDCAuthenticationRequest)prc.getOutboundMessageContext()
+ .getMessage()).getRequestedClaims().getUserInfoClaimsRequest().get("family_name", null));
+ }
+
+ @Test
+ public void testNoRequestedClaims() throws ComponentInitializationException {
+
+ action.initialize();
+
+ final Event event = action.execute(src);
+ assertNull(event);
+ assertNotNull(prc.getOutboundMessageContext().getMessage());
+ assertNull(((OIDCAuthenticationRequest)prc.getOutboundMessageContext()
+ .getMessage()).getRequestedClaims());
+ }
+
+}
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 a52124b..8ec7aeb 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
@@ -28,7 +28,6 @@ import static org.testng.Assert.assertTrue;
import java.io.IOException;
import java.net.URI;
import java.net.URLEncoder;
-import java.security.KeyException;
import java.util.ArrayList;
import javax.annotation.Nonnull;
@@ -70,7 +69,6 @@ import org.springframework.webflow.executor.FlowExecutorImpl;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
-import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JWEAlgorithm;
import com.nimbusds.jose.jwk.KeyUse;
import com.nimbusds.jose.jwk.RSAKey;
diff --git a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/BuildRequestObjectTest.java b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/BuildRequestObjectTest.java
new file mode 100644
index 0000000..958bd7f
--- /dev/null
+++ b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/BuildRequestObjectTest.java
@@ -0,0 +1,130 @@
+package net.shibboleth.idp.plugin.authn.oidc.rp.impl;
+
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+import org.opensaml.messaging.context.navigate.ChildContextLookup;
+import org.opensaml.messaging.context.navigate.ParentContextLookup;
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.springframework.webflow.execution.Event;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.nimbusds.oauth2.sdk.ResponseMode;
+import com.nimbusds.oauth2.sdk.ResponseType;
+import com.nimbusds.openid.connect.sdk.Nonce;
+import com.nimbusds.openid.connect.sdk.OIDCClaimsRequest;
+import com.nimbusds.openid.connect.sdk.assurance.claims.VerifiedClaimsSetRequest;
+import com.nimbusds.openid.connect.sdk.claims.ClaimsSet;
+
+import net.shibboleth.idp.authn.context.AuthenticationContext;
+import net.shibboleth.idp.profile.context.RelyingPartyContext;
+import net.shibboleth.idp.profile.context.navigate.WebflowRequestContextProfileRequestContextLookup;
+import net.shibboleth.idp.relyingparty.RelyingPartyConfiguration;
+import net.shibboleth.oidc.profile.config.OIDCAuthorizationConfiguration;
+import net.shibboleth.oidc.profile.core.OIDCAuthenticationRequest;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+
+/** Tests for the {@link BuildRequestObject} action.*/
+public class BuildRequestObjectTest extends AbstractOIDCTest {
+
+ /** The action to test.*/
+ private BuildRequestObject action;
+
+ /** The RPC.*/
+ private RelyingPartyContext rpc;
+
+ /** The profile config.*/
+ private OIDCAuthorizationConfiguration oidcAuthzConfig;
+
+ @Override
+ @BeforeMethod
+ public void setup() throws Exception {
+ super.setup();
+ action = new BuildRequestObject();
+
+ rpc = prc.getSubcontext(RelyingPartyContext.class, true);
+ oidcAuthzConfig = new OIDCAuthorizationConfiguration();
+ final RelyingPartyConfiguration rpConfig = new RelyingPartyConfiguration();
+ rpc.setProfileConfig(oidcAuthzConfig);
+ rpc.setConfiguration(rpConfig);
+
+ action.setProfileContextLookupStrategy(new ChildContextLookup<>(ProfileRequestContext.class).compose(
+ new ChildContextLookup<>(AuthenticationContext.class)
+ .compose(new WebflowRequestContextProfileRequestContextLookup())));
+
+ action.setAuthenticationContextLookupStrategy(new ParentContextLookup<>(AuthenticationContext.class));
+
+ // Setup a basic authentication request
+ authnRequest.setNonce(new Nonce());
+ authnRequest.setResponseType(ResponseType.CODE);
+ authnRequest.setResponseMode(ResponseMode.QUERY);
+ authnRequest.setDefaultResponseMode(ResponseMode.QUERY);
+ }
+
+ @Test
+ public void testBuildRequestObject_Success() throws ComponentInitializationException {
+
+ action.initialize();
+ final Event event = action.execute(src);
+ assertNull(event);
+ assertNotNull(prc.getOutboundMessageContext().getMessage());
+ assertNotNull(((OIDCAuthenticationRequest)prc.getOutboundMessageContext()
+ .getMessage()).getRequestObjectClaimsSet());
+ final ClaimsSet claims = (((OIDCAuthenticationRequest)prc.getOutboundMessageContext()
+ .getMessage()).getRequestObjectClaimsSet());
+ assertEquals(claims.getStringClaim("scope"),"openid");
+ assertEquals(claims.getStringClaim("iss"),"https://rp.example.com");
+ assertEquals(claims.getStringClaim("client_id"),"https://rp.example.com");
+ assertEquals(claims.getStringClaim("response_type"),"code");
+ assertEquals(claims.getStringClaim("redirect_uri"),"https://rp.example.com/callback");
+ assertNotNull(claims.getStringClaim("nonce"));
+ assertNotNull(claims.getClaim("aud"));
+
+ assertTrue(isValidJSON(claims.toJSONString()));
+ }
+
+ @Test
+ public void testBuildRequestObject_WithRequestedClaims_Success() throws ComponentInitializationException {
+
+ final OIDCClaimsRequest requestedClaims = new OIDCClaimsRequest()
+ .withIDTokenClaimsRequest(new VerifiedClaimsSetRequest().add("given_name"))
+ .withUserInfoClaimsRequest(new VerifiedClaimsSetRequest().add("family_name"));
+ authnRequest.setRequestedClaims(requestedClaims);
+
+ action.initialize();
+ final Event event = action.execute(src);
+ assertNull(event);
+ assertNotNull(prc.getOutboundMessageContext().getMessage());
+ assertNotNull(((OIDCAuthenticationRequest)prc.getOutboundMessageContext()
+ .getMessage()).getRequestObjectClaimsSet());
+ final ClaimsSet claims = (((OIDCAuthenticationRequest)prc.getOutboundMessageContext()
+ .getMessage()).getRequestObjectClaimsSet());
+ assertEquals(claims.getStringClaim("scope"),"openid");
+ assertEquals(claims.getStringClaim("iss"),"https://rp.example.com");
+ assertEquals(claims.getStringClaim("client_id"),"https://rp.example.com");
+ assertEquals(claims.getStringClaim("response_type"),"code");
+ assertEquals(claims.getStringClaim("redirect_uri"),"https://rp.example.com/callback");
+ assertNotNull(claims.getStringClaim("nonce"));
+ assertNotNull(claims.getClaim("aud"));
+ assertNotNull(claims.getClaim("claims"));
+ assertTrue(isValidJSON(claims.getClaim("claims").toString()));
+
+ assertTrue(isValidJSON(claims.toJSONString()));
+ }
+
+ private boolean isValidJSON(final String json) {
+ try{
+ final ObjectMapper objectMapper = new ObjectMapper();
+ objectMapper.readTree(json);
+ } catch(final Exception e){
+ return false;
+ }
+ return true;
+ }
+
+}
diff --git a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/test/flow/AbstractAuthnXmlFlowExecutionTests.java b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/test/flow/AbstractAuthnXmlFlowExecutionTests.java
index 7003e42..75cbf1b 100644
--- a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/test/flow/AbstractAuthnXmlFlowExecutionTests.java
+++ b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/test/flow/AbstractAuthnXmlFlowExecutionTests.java
@@ -341,7 +341,11 @@ public abstract class AbstractAuthnXmlFlowExecutionTests extends CustomAbstractX
addBeanDefinition(builderContext, "shibboleth.Functions.Expression",BeanDefinitionBuilder.
genericBeanDefinition(net.shibboleth.ext.spring.util.SpringExpressionFunction.class)
- .setAbstract(true).getBeanDefinition());
+ .setAbstract(true).getBeanDefinition());
+
+ addBeanDefinition(builderContext, "shibboleth.Functions.Scripted",BeanDefinitionBuilder.
+ genericBeanDefinition(net.shibboleth.utilities.java.support.logic.ScriptedFunction.class)
+ .setAbstract(true).getBeanDefinition());
addBeanDefinition(builderContext, "shibboleth.BiFunctions.Expression",BeanDefinitionBuilder.
genericBeanDefinition(net.shibboleth.ext.spring.util.SpringExpressionBiFunction.class)
diff --git a/idp-oidc-rp-impl/src/test/resources/metadata/test-provider-requestobject-encrypt.json b/idp-oidc-rp-impl/src/test/resources/metadata/test-provider-requestobject-encrypt.json
index 17c2156..02633d9 100644
--- a/idp-oidc-rp-impl/src/test/resources/metadata/test-provider-requestobject-encrypt.json
+++ b/idp-oidc-rp-impl/src/test/resources/metadata/test-provider-requestobject-encrypt.json
@@ -6,6 +6,7 @@
"userinfo_endpoint":"https://localhost:9921/v1/userinfo",
"revocation_endpoint":"https://localhost:9921/revoke",
"jwks_uri":"https://localhost:9921/oauth2/v3/certs",
+ "claims_parameter_supported":true,
"request_parameter_supported":true,
"response_types_supported":[
"code",
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list