[java-idp-oidc] branch main updated: JOIDC-104 - Support to manipulate claims within the ID_Token
Henri Mikkonen
henri.mikkonen at iki.fi
Fri Jun 10 07:00:56 UTC 2022
This is an automated email from the git hooks/post-receive script.
hjmikkon pushed a commit to branch main
in repository java-idp-oidc.
View the commit online:
http://git.shibboleth.net/view/?p=java-idp-oidc.git;a=commit;h=ee177c7d13f3f78920e2972cc6e2782bda34b006
The following commit(s) were added to refs/heads/main by this push:
new ee177c7d JOIDC-104 - Support to manipulate claims within the ID_Token
ee177c7d is described below
commit ee177c7d13f3f78920e2972cc6e2782bda34b006
Author: Henri Mikkonen <henri.mikkonen at iki.fi>
AuthorDate: Fri Jun 10 10:00:28 2022 +0300
JOIDC-104 - Support to manipulate claims within the ID_Token
https://shibboleth.atlassian.net/browse/JOIDC-104
Improved unit and flow testing.
---
.../oidc/op/profile/flow/AuthorizeFlowTest.java | 9 ++-
.../plugin/oidc/op/profile/flow/TokenFlowTest.java | 6 ++
.../impl/ManipulateClaimsForIDTokenTest.java | 81 +++++++++++++++++++++-
.../src/test/resources/conf/global.xml | 12 ++++
.../src/test/resources/conf/relying-party.xml | 4 +-
5 files changed, 106 insertions(+), 6 deletions(-)
diff --git a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/AuthorizeFlowTest.java b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/AuthorizeFlowTest.java
index 575adcfd..fc3fe75e 100644
--- a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/AuthorizeFlowTest.java
+++ b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/AuthorizeFlowTest.java
@@ -46,6 +46,7 @@ import com.nimbusds.openid.connect.sdk.AuthenticationResponse;
import com.nimbusds.openid.connect.sdk.AuthenticationSuccessResponse;
import com.nimbusds.openid.connect.sdk.claims.ClaimRequirement;
import com.nimbusds.openid.connect.sdk.claims.ClaimsSetRequest;
+import com.nimbusds.openid.connect.sdk.claims.IDTokenClaimsSet;
import net.shibboleth.idp.plugin.oidc.op.token.support.AccessTokenClaimsSet;
import net.shibboleth.idp.plugin.oidc.op.token.support.AuthorizeCodeClaimsSet;
@@ -467,7 +468,8 @@ public class AuthorizeFlowTest extends AbstractOidcFlowTest {
}
@Test
- public void testWithHybridIdTokenTokenFlowWithCustomTokenClaim() throws IOException, SessionException, ParseException, DataSealerException {
+ public void testWithHybridIdTokenTokenFlowWithCustomTokenClaim() throws IOException, SessionException,
+ ParseException, DataSealerException, com.nimbusds.oauth2.sdk.ParseException {
request.setMethod("GET");
request.setQueryString("client_id=mockClientIdCustomTokens&response_type=code+id_token+token&scope=openid%20profile"
+ "&redirect_uri="+ redirectUri + "&nonce=idhas3h23hi13h1o2i32");
@@ -484,6 +486,11 @@ public class AuthorizeFlowTest extends AbstractOidcFlowTest {
Assert.assertNotNull(successResponse.getAuthorizationCode());
Assert.assertNull(successResponse.getIssuer());
+ final IDTokenClaimsSet idToken = new IDTokenClaimsSet(successResponse.getIDToken().getJWTClaimsSet());
+ Assert.assertNotNull(idToken);
+ Assert.assertNotNull(idToken.getStringClaim("custom_id_token_claim"));
+ Assert.assertEquals(idToken.getStringClaim("custom_id_token_claim"), "value1");
+
final AccessTokenClaimsSet token =
AccessTokenClaimsSet.parse(successResponse.getAccessToken().getValue(), getDataSealer());
Assert.assertEquals(token.getAudience(), Collections.singletonList(issuer));
diff --git a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/TokenFlowTest.java b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/TokenFlowTest.java
index 8aa9ace5..12d7ecc4 100644
--- a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/TokenFlowTest.java
+++ b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/TokenFlowTest.java
@@ -50,6 +50,7 @@ import com.nimbusds.oauth2.sdk.token.AccessToken;
import com.nimbusds.oauth2.sdk.token.RefreshToken;
import com.nimbusds.openid.connect.sdk.OIDCTokenResponse;
import com.nimbusds.openid.connect.sdk.claims.ClaimsSet;
+import com.nimbusds.openid.connect.sdk.claims.IDTokenClaimsSet;
import net.minidev.json.JSONObject;
import net.shibboleth.idp.plugin.oidc.op.profile.impl.ValidateGrantTest;
@@ -201,6 +202,11 @@ public class TokenFlowTest extends AbstractOidcClientAuthenticationFlowTest {
Assert.assertNotNull(response.getTokens().getRefreshToken());
Assert.assertNotNull(response.getOIDCTokens().getIDToken());
+ final IDTokenClaimsSet idToken = new IDTokenClaimsSet(response.getOIDCTokens().getIDToken().getJWTClaimsSet());
+ Assert.assertNotNull(idToken);
+ Assert.assertNotNull(idToken.getStringClaim("custom_id_token_claim"));
+ Assert.assertEquals(idToken.getStringClaim("custom_id_token_claim"), "value1");
+
final AccessTokenClaimsSet accessToken =
AccessTokenClaimsSet.parse(response.getTokens().getAccessToken().getValue(), getDataSealer());
final String atCustomAtClaim = accessToken.getClaimsSet().getStringClaim("custom_access_token_claim");
diff --git a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/ManipulateClaimsForIDTokenTest.java b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/ManipulateClaimsForIDTokenTest.java
index 0ef45578..5dd088bb 100644
--- a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/ManipulateClaimsForIDTokenTest.java
+++ b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/ManipulateClaimsForIDTokenTest.java
@@ -36,6 +36,7 @@ import org.testng.annotations.Test;
import com.nimbusds.oauth2.sdk.ParseException;
import com.nimbusds.oauth2.sdk.id.Audience;
+import com.nimbusds.openid.connect.sdk.claims.AMR;
import com.nimbusds.openid.connect.sdk.claims.IDTokenClaimsSet;
/** {@link ManipulateClaimsForIDToken} unit test. */
@@ -63,24 +64,87 @@ public class ManipulateClaimsForIDTokenTest extends BaseOIDCResponseActionTest {
ActionTestingSupport.assertEvent(event, EventIds.INVALID_MSG_CTX);
}
-
+
+ @Test
+ public void testSuccessSameMapDoesntChangeContents() throws ComponentInitializationException, ParseException {
+ final Instant now = Instant.now();
+ setIdTokenToResponseContext("iss", "sub", "aud", now, now);
+ Assert.assertEquals(respCtx.getIDToken().toJSONObject().size(), 5);
+ init((prc, map) -> map);
+ final Event event = action.execute(requestCtx);
+ ActionTestingSupport.assertProceedEvent(event);
+ final IDTokenClaimsSet idToken = respCtx.getIDToken();
+ Assert.assertEquals(idToken.toJSONObject().size(), 5);
+ Assert.assertEquals(idToken.getSubject().getValue(), "sub");
+ Assert.assertEquals(idToken.getIssuer().getValue(), "iss");
+ Assert.assertEquals(idToken.getAudience(), Audience.create("aud"));
+ Assert.assertEquals(idToken.getIssueTime().toInstant().getEpochSecond(), now.getEpochSecond());
+ Assert.assertEquals(idToken.getExpirationTime().toInstant().getEpochSecond(), now.getEpochSecond());
+ }
+
@Test
public void testSuccessManipulationForIss() throws ComponentInitializationException, ParseException {
final Instant now = Instant.now();
setIdTokenToResponseContext("iss", "sub", "aud", now, now);
+ Assert.assertEquals(respCtx.getIDToken().toJSONObject().size(), 5);
final Map<String, Object> manipulatedClaims = Map.of("iss", "manipulatedIss", "sub", "sub", "aud",
List.of("aud"), "exp", now.getEpochSecond(), "iat", now.getEpochSecond());
init(mockFunction(manipulatedClaims));
final Event event = action.execute(requestCtx);
ActionTestingSupport.assertProceedEvent(event);
final IDTokenClaimsSet idToken = respCtx.getIDToken();
+ Assert.assertEquals(idToken.toJSONObject().size(), 5);
Assert.assertEquals(idToken.getSubject().getValue(), "sub");
Assert.assertEquals(idToken.getIssuer().getValue(), "manipulatedIss");
Assert.assertEquals(idToken.getAudience(), Audience.create("aud"));
Assert.assertEquals(idToken.getIssueTime().toInstant().getEpochSecond(), now.getEpochSecond());
Assert.assertEquals(idToken.getExpirationTime().toInstant().getEpochSecond(), now.getEpochSecond());
}
-
+
+ @Test
+ public void testSuccessManipulationAddStandardClaims() throws ComponentInitializationException, ParseException {
+ final Instant now = Instant.now();
+ setIdTokenToResponseContext("iss", "sub", "aud", now, now);
+ Assert.assertEquals(respCtx.getIDToken().toJSONObject().size(), 5);
+ final Map<String, Object> manipulatedClaims = Map.of("iss", "manipulatedIss", "sub", "sub", "aud",
+ List.of("aud"), "exp", now.getEpochSecond(), "iat", now.getEpochSecond(), "acr", "password",
+ "amr", List.of("face"));
+ init(mockFunction(manipulatedClaims));
+ final Event event = action.execute(requestCtx);
+ ActionTestingSupport.assertProceedEvent(event);
+ final IDTokenClaimsSet idToken = respCtx.getIDToken();
+ Assert.assertEquals(idToken.toJSONObject().size(), 7);
+ Assert.assertEquals(idToken.getSubject().getValue(), "sub");
+ Assert.assertEquals(idToken.getIssuer().getValue(), "manipulatedIss");
+ Assert.assertEquals(idToken.getAudience(), Audience.create("aud"));
+ Assert.assertEquals(idToken.getIssueTime().toInstant().getEpochSecond(), now.getEpochSecond());
+ Assert.assertEquals(idToken.getExpirationTime().toInstant().getEpochSecond(), now.getEpochSecond());
+ Assert.assertEquals(idToken.getACR().getValue(), "password");
+ Assert.assertEquals(idToken.getAMR(), List.of(AMR.FACE));
+ }
+
+ @Test
+ public void testSuccessManipulationAddCustomClaims() throws ComponentInitializationException, ParseException {
+ final Instant now = Instant.now();
+ setIdTokenToResponseContext("iss", "sub", "aud", now, now);
+ Assert.assertEquals(respCtx.getIDToken().toJSONObject().size(), 5);
+ final Map<String, Object> manipulatedClaims = Map.of("iss", "manipulatedIss", "sub", "sub", "aud",
+ List.of("aud"), "exp", now.getEpochSecond(), "iat", now.getEpochSecond(), "custom1", 3,
+ "custom2", List.of("customV1", "customV2"));
+ init(mockFunction(manipulatedClaims));
+ final Event event = action.execute(requestCtx);
+ ActionTestingSupport.assertProceedEvent(event);
+ final IDTokenClaimsSet idToken = respCtx.getIDToken();
+ Assert.assertEquals(idToken.toJSONObject().size(), 7);
+ Assert.assertEquals(idToken.getSubject().getValue(), "sub");
+ Assert.assertEquals(idToken.getIssuer().getValue(), "manipulatedIss");
+ Assert.assertEquals(idToken.getAudience(), Audience.create("aud"));
+ Assert.assertEquals(idToken.getIssueTime().toInstant().getEpochSecond(), now.getEpochSecond());
+ Assert.assertEquals(idToken.getExpirationTime().toInstant().getEpochSecond(), now.getEpochSecond());
+ Assert.assertEquals(idToken.getNumberClaim("custom1").toString(), Integer.valueOf(3).toString());
+ Assert.assertEquals(idToken.getStringListClaim("custom2"), List.of("customV1", "customV2"));
+ }
+
@Test
public void testFailedManipulationDueMissingIss() throws ComponentInitializationException, ParseException {
final Instant now = Instant.now();
@@ -91,7 +155,18 @@ public class ManipulateClaimsForIDTokenTest extends BaseOIDCResponseActionTest {
final Event event = action.execute(requestCtx);
ActionTestingSupport.assertEvent(event, IdPEventIds.INVALID_PROFILE_CONFIG);
}
-
+
+ @Test
+ public void testFailedManipulationDueInvalidIatFormat() throws ComponentInitializationException, ParseException {
+ final Instant now = Instant.now();
+ setIdTokenToResponseContext("iss", "sub", "aud", now, now);
+ final Map<String, Object> manipulatedClaims = Map.of("iss", "iss", "sub", "sub", "aud",
+ List.of("aud"), "exp", now.getEpochSecond(), "iat", "invalidFormat");
+ init(mockFunction(manipulatedClaims));
+ final Event event = action.execute(requestCtx);
+ ActionTestingSupport.assertEvent(event, IdPEventIds.INVALID_PROFILE_CONFIG);
+ }
+
@SuppressWarnings({"rawtypes", "unchecked"})
protected BiFunction<ProfileRequestContext,Map<String,Object>,Map<String,Object>> mockFunction(
final Map<String, Object> result) {
diff --git a/idp-oidc-extension-impl/src/test/resources/conf/global.xml b/idp-oidc-extension-impl/src/test/resources/conf/global.xml
index 74c52462..925dd47f 100644
--- a/idp-oidc-extension-impl/src/test/resources/conf/global.xml
+++ b/idp-oidc-extension-impl/src/test/resources/conf/global.xml
@@ -39,6 +39,18 @@
<bean id="testbed.DefaultRSSigningCredential" parent="shibboleth.JWKCredential"
p:resource="%{idp.signing.oidc.rs.key}" />
+ <bean id="testIDTokenManipulation" parent="shibboleth.BiFunctions.Scripted" factory-method="inlineScript">
+ <constructor-arg name="scriptSource">
+ <value>
+ <![CDATA[
+ newMap = input2;
+ newMap.put("custom_id_token_claim", "value1");
+ newMap;
+ ]]>
+ </value>
+ </constructor-arg>
+ </bean>
+
<bean id="testAuthorizationCodeManipulation" parent="shibboleth.BiFunctions.Scripted" factory-method="inlineScript">
<constructor-arg name="scriptSource">
<value>
diff --git a/idp-oidc-extension-impl/src/test/resources/conf/relying-party.xml b/idp-oidc-extension-impl/src/test/resources/conf/relying-party.xml
index 68e843f0..9e7dfb46 100644
--- a/idp-oidc-extension-impl/src/test/resources/conf/relying-party.xml
+++ b/idp-oidc-extension-impl/src/test/resources/conf/relying-party.xml
@@ -70,8 +70,8 @@
<bean parent="RelyingPartyByName" c:relyingPartyIds="mockClientIdCustomTokens">
<property name="profileConfigurations">
<list>
- <bean parent="OIDC.SSO.MDDriven" p:authorizationCodeClaimsSetManipulationStrategy-ref="testAuthorizationCodeManipulation" p:accessTokenClaimsSetManipulationStrategy-ref="testAccessTokenManipulation" />
- <bean parent="OAUTH2.Token.MDDriven" p:forcePKCE="false" p:allowPKCEPlain="true" p:accessTokenClaimsSetManipulationStrategy-ref="testAccessTokenManipulation" p:refreshTokenClaimsSetManipulationStrategy-ref="testRefreshTokenManipulation"/>
+ <bean parent="OIDC.SSO.MDDriven" p:IDTokenManipulationStrategy-ref="testIDTokenManipulation" p:authorizationCodeClaimsSetManipulationStrategy-ref="testAuthorizationCodeManipulation" p:accessTokenClaimsSetManipulationStrategy-ref="testAccessTokenManipulation" />
+ <bean parent="OAUTH2.Token.MDDriven" p:forcePKCE="false" p:allowPKCEPlain="true" p:IDTokenManipulationStrategy-ref="testIDTokenManipulation" p:accessTokenClaimsSetManipulationStrategy-ref="testAccessTokenManipulation" p:refreshTokenClaimsSetManipulationStrategy-ref="testRefreshTokenManipulation"/>
</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