[java-idp-plugin-oidc-rp] branch main updated: Add more flow tests for id_token and userinfo token claims
Phil Smart
philip.smart at jisc.ac.uk
Wed Feb 15 17:34:35 UTC 2023
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=0cd108c91b81b6edbad41275287fbaa759f43c44
The following commit(s) were added to refs/heads/main by this push:
new 0cd108c Add more flow tests for id_token and userinfo token claims
0cd108c is described below
commit 0cd108c91b81b6edbad41275287fbaa759f43c44
Author: Phil Smart <philip.smart at jisc.ac.uk>
AuthorDate: Wed Feb 15 17:34:30 2023 +0000
Add more flow tests for id_token and userinfo token claims
---
.../OIDCRPFlowFromAuthenticationResponseTest.java | 277 ++++++++++++++++-----
.../plugin/authn/oidc/rp/impl/TestTokenHelper.java | 144 ++++++-----
2 files changed, 300 insertions(+), 121 deletions(-)
diff --git a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/OIDCRPFlowFromAuthenticationResponseTest.java b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/OIDCRPFlowFromAuthenticationResponseTest.java
index 0a1a43c..8ac0f58 100644
--- a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/OIDCRPFlowFromAuthenticationResponseTest.java
+++ b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/OIDCRPFlowFromAuthenticationResponseTest.java
@@ -2,6 +2,7 @@
package net.shibboleth.idp.plugin.authn.oidc.rp.impl;
import java.net.URI;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -105,10 +106,11 @@ public class OIDCRPFlowFromAuthenticationResponseTest extends OIDCRPFlowTest {
final MockWebServer mockOPServer = createSimpleServer();
final var accessTokenResp = TestTokenHelper.createAccessTokenResponseJSON(
- OP_ISSUER_ID, CLIENT_ID, List.of(CLIENT_ID), JWSAlgorithm.HS256, null, null,
- new DefaultClientSecretCredential(CLIENT_SECRET).toSigningCredential(), null);
+ Map.of("iss", OP_ISSUER_ID, "azp", CLIENT_ID, "aud", List.of(CLIENT_ID)),
+ JWSAlgorithm.HS256, null, null, new DefaultClientSecretCredential(CLIENT_SECRET).toSigningCredential(),
+ null);
final var userInfoResp =
- TestTokenHelper.createPlainUserInfoResponseString(OP_ISSUER_ID, List.of(CLIENT_ID),"jdoe");
+ TestTokenHelper.createPlainUserInfoResponseString(Map.of("iss", OP_ISSUER_ID, "aud", List.of(CLIENT_ID)));
// First is token exchange
queueMockServerResponse(mockOPServer, 200, accessTokenResp, "application/json");
// Second is plain userInfo
@@ -127,43 +129,6 @@ public class OIDCRPFlowFromAuthenticationResponseTest extends OIDCRPFlowTest {
assertEndUserClaimsVerified(nestedPrc);
}
- /**
- * Test the flow from the external authorization request to the end of the flow.
- * Using a MAC signed id_token and an invalid UserInfo JSON Response - it has no subject.
- *
- * @throws Exception on error.
- */
- @Test
- public void test_IDTokenHS256_InvalidPlainUserInfo() throws Exception {
-
- basicSetup();
-
- final MockWebServer mockOPServer = createSimpleServer();
- final var accessTokenResp = TestTokenHelper.createAccessTokenResponseJSON(
- OP_ISSUER_ID, CLIENT_ID, List.of(CLIENT_ID), JWSAlgorithm.HS256, null, null,
- new DefaultClientSecretCredential(CLIENT_SECRET).toSigningCredential(), null);
- final var userInfoResp =
- TestTokenHelper.createPlainUserInfoResponseString(OP_ISSUER_ID, List.of(CLIENT_ID), null);
-
- // First is token exchange
- queueMockServerResponse(mockOPServer, 200, accessTokenResp, "application/json");
- // Second is plain userInfo
- queueMockServerResponse(mockOPServer, 200, userInfoResp, "application/json");
-
- mockOPServer.start(9918);
-
- final var prc = resumeBasicFlow();
-
- mockOPServer.shutdown();
-
- // Assert test conditions
-
- assertFlowExecutionEnded();
- assertIdTokenSignatureAndClaimsVerified(
- prc.getSubcontext(AuthenticationContext.class).getSubcontext(ProfileRequestContext.class));
- // Should have failed to produce a result
- assertFlowEndedInErrorConditions(prc, "InvalidUserInfoClaims");
- }
@Test
public void test_IDTokenHS256_UserInfoHS256() throws Exception {
@@ -172,11 +137,12 @@ public class OIDCRPFlowFromAuthenticationResponseTest extends OIDCRPFlowTest {
final MockWebServer mockOPServer = createSimpleServer();
final var accessTokenResp = TestTokenHelper.createAccessTokenResponseJSON(
- OP_ISSUER_ID, CLIENT_ID, List.of(CLIENT_ID), JWSAlgorithm.HS256, null, null,
- new DefaultClientSecretCredential(CLIENT_SECRET).toSigningCredential(), null);
+ Map.of("iss", OP_ISSUER_ID, "azp", CLIENT_ID, "aud", List.of(CLIENT_ID)),
+ JWSAlgorithm.HS256, null, null, new DefaultClientSecretCredential(CLIENT_SECRET).toSigningCredential(),
+ null);
final var userInfoResp = TestTokenHelper.createJWTUserInfoResponse(
- OP_ISSUER_ID, List.of(CLIENT_ID), "jdoe", JWSAlgorithm.HS256, null, null,
- new DefaultClientSecretCredential(CLIENT_SECRET).toSigningCredential(), null);
+ Map.of("iss", OP_ISSUER_ID, "aud", List.of(CLIENT_ID)), JWSAlgorithm.HS256, null,
+ null, new DefaultClientSecretCredential(CLIENT_SECRET).toSigningCredential(), null);
// First is token exchange
queueMockServerResponse(mockOPServer, 200, accessTokenResp, "application/json");
@@ -206,8 +172,8 @@ public class OIDCRPFlowFromAuthenticationResponseTest extends OIDCRPFlowTest {
final MockWebServer mockOPServer = createSimpleServer();
final var accessTokenResp = TestTokenHelper.createAccessTokenResponseJSON(
- OP_ISSUER_ID, CLIENT_ID, List.of(CLIENT_ID), JWSAlgorithm.HS256, JWEAlgorithm.DIR,
- EncryptionMethod.A128CBC_HS256,
+ Map.of("iss", OP_ISSUER_ID, "azp", CLIENT_ID, "aud", List.of(CLIENT_ID)),
+ JWSAlgorithm.HS256, JWEAlgorithm.DIR, EncryptionMethod.A128CBC_HS256,
new DefaultClientSecretCredential(CLIENT_SECRET).toSigningCredential(),
new DefaultClientSecretCredential(CLIENT_SECRET).toEncryptionCredential(
JWEAlgorithm.DIR, EncryptionMethod.A128CBC_HS256));
@@ -218,10 +184,10 @@ public class OIDCRPFlowFromAuthenticationResponseTest extends OIDCRPFlowTest {
.keyUse(KeyUse.ENCRYPTION)
.generate();
final var userInfoResp = TestTokenHelper.createJWTUserInfoResponse(
- OP_ISSUER_ID, List.of(CLIENT_ID), "jdoe", JWSAlgorithm.ES256, JWEAlgorithm.RSA_OAEP_256,
+ Map.of("iss", OP_ISSUER_ID, "aud", List.of(CLIENT_ID)), JWSAlgorithm.ES256,
+ JWEAlgorithm.RSA_OAEP_256,
EncryptionMethod.A256GCM,
- new BasicCredential(sigKey.toPublicKey(), sigKey.toPrivateKey()),
- new BasicCredential(encKey.toPublicKey(), encKey.toPrivateKey()));
+ new BasicCredential(sigKey.toPublicKey(), sigKey.toPrivateKey()), new BasicCredential(encKey.toPublicKey(), encKey.toPrivateKey()));
// First is token exchange
queueMockServerResponse(mockOPServer, 200, accessTokenResp, "application/json");
@@ -306,13 +272,13 @@ public class OIDCRPFlowFromAuthenticationResponseTest extends OIDCRPFlowTest {
.keyUse(KeyUse.ENCRYPTION)
.generate();
final var accessTokenResp = TestTokenHelper.createAccessTokenResponseJSON(
- OP_ISSUER_ID, CLIENT_ID, List.of(CLIENT_ID), JWSAlgorithm.HS256, JWEAlgorithm.RSA_OAEP_256,
- EncryptionMethod.A256GCM,
+ Map.of("iss", OP_ISSUER_ID, "azp", CLIENT_ID, "aud", List.of(CLIENT_ID)),
+ JWSAlgorithm.HS256, JWEAlgorithm.RSA_OAEP_256, EncryptionMethod.A256GCM,
new DefaultClientSecretCredential(CLIENT_SECRET).toSigningCredential(),
new BasicCredential(encKey.toPublicKey(), encKey.toPrivateKey()));
final var userInfoResp =
- TestTokenHelper.createPlainUserInfoResponseString(OP_ISSUER_ID, List.of(CLIENT_ID), "jdoe");
+ TestTokenHelper.createPlainUserInfoResponseString(Map.of("iss", OP_ISSUER_ID, "aud", List.of(CLIENT_ID)));
// First is token exchange
queueMockServerResponse(mockOPServer, 200, accessTokenResp, "application/json");
@@ -376,11 +342,12 @@ public class OIDCRPFlowFromAuthenticationResponseTest extends OIDCRPFlowTest {
final MockWebServer mockOPServer = createSimpleServer();
final var accessTokenResp = TestTokenHelper.createAccessTokenResponseJSON(
- OP_ISSUER_ID, CLIENT_ID, List.of(CLIENT_ID), JWSAlgorithm.HS256, null, null,
- new DefaultClientSecretCredential(CLIENT_SECRET).toSigningCredential(), null);
+ Map.of("iss", OP_ISSUER_ID, "azp", CLIENT_ID, "aud", List.of(CLIENT_ID)),
+ JWSAlgorithm.HS256, null, null, new DefaultClientSecretCredential(CLIENT_SECRET).toSigningCredential(),
+ null);
final var userInfoResp =
- TestTokenHelper.createPlainJWTUserInfoResponseJSON(OP_ISSUER_ID,CLIENT_ID)
- .serialize();
+ TestTokenHelper.createPlainJWTUserInfoResponseJSON(
+ Map.of("iss", OP_ISSUER_ID, "aud", List.of(CLIENT_ID))).serialize();
// First is token exchange
queueMockServerResponse(mockOPServer, 200, accessTokenResp, "application/json");
// Second is plain userInfo (tell it is a JWT type when it is not)
@@ -404,11 +371,12 @@ public class OIDCRPFlowFromAuthenticationResponseTest extends OIDCRPFlowTest {
final MockWebServer mockOPServer = createSimpleServer();
final var accessTokenResp = TestTokenHelper.createAccessTokenResponseJSON(
- OP_ISSUER_ID, CLIENT_ID, List.of(CLIENT_ID), JWSAlgorithm.HS256, null, null,
+ Map.of("iss", OP_ISSUER_ID, "azp", CLIENT_ID, "aud", List.of(CLIENT_ID)),
+ JWSAlgorithm.HS256, null, null,
new DefaultClientSecretCredential(CLIENT_SECRET).toSigningCredential(), null);
final var userInfoResp = TestTokenHelper.createJWTUserInfoResponse(
- OP_ISSUER_ID, List.of(CLIENT_ID), "jdoe", JWSAlgorithm.HS256, null, null,
- new DefaultClientSecretCredential(CLIENT_SECRET).toSigningCredential(), null);
+ Map.of("iss", OP_ISSUER_ID, "aud", List.of(CLIENT_ID)), JWSAlgorithm.HS256, null,
+ null, new DefaultClientSecretCredential(CLIENT_SECRET).toSigningCredential(), null);
// First is token exchange
queueMockServerResponse(mockOPServer, 200, accessTokenResp, "application/json");
@@ -528,5 +496,196 @@ public class OIDCRPFlowFromAuthenticationResponseTest extends OIDCRPFlowTest {
assertFlowEndedInErrorConditions(prc, "MessageProcessingError");
}
+
+ /**
+ * Test a suitable error occurs if the id_token does not contain an issuer.
+ *
+ * @throws Exception on error.
+ */
+ @Test
+ public void test_IDTokenHS256_NoIssuer_PlainUserInfo() throws Exception {
+
+ basicSetup();
+
+ final MockWebServer mockOPServer = createSimpleServer();
+
+ final var accessTokenResp = TestTokenHelper.createAccessTokenResponseJSON(Map.of("iss","", "azp",
+ CLIENT_ID, "aud", List.of(CLIENT_ID)),
+ JWSAlgorithm.HS256, null, null,
+ new DefaultClientSecretCredential(CLIENT_SECRET).toSigningCredential(), null);
+ final var userInfoResp =
+ TestTokenHelper.createPlainUserInfoResponseString(Map.of("iss", OP_ISSUER_ID, "aud", List.of(CLIENT_ID)));
+ // First is token exchange
+ queueMockServerResponse(mockOPServer, 200, accessTokenResp, "application/json");
+ // Second is plain userInfo
+ queueMockServerResponse(mockOPServer, 200, userInfoResp, "application/json");
+ mockOPServer.start(9918);
+
+ final var prc = resumeBasicFlow();
+ mockOPServer.shutdown();
+
+ // Assert test conditions
+ assertFlowEndedInErrorConditions(prc, "InvalidToken");
+ }
+
+ /**
+ * Test a suitable error occurs if the id_token does not contain a subject.
+ *
+ * @throws Exception on error.
+ */
+ @Test
+ public void test_IDTokenHS256_NoSub_PlainUserInfo() throws Exception {
+
+ basicSetup();
+
+ final MockWebServer mockOPServer = createSimpleServer();
+ final var accessTokenResp = TestTokenHelper.createAccessTokenResponseJSON(Map.of("sub","","iss",
+ OP_ISSUER_ID, "azp", CLIENT_ID, "aud", List.of(CLIENT_ID)),
+ JWSAlgorithm.HS256, null, null,
+ new DefaultClientSecretCredential(CLIENT_SECRET).toSigningCredential(), null);
+
+ final var userInfoResp =
+ TestTokenHelper.createPlainUserInfoResponseString(Map.of("iss", OP_ISSUER_ID, "aud", List.of(CLIENT_ID)));
+ // First is token exchange
+ queueMockServerResponse(mockOPServer, 200, accessTokenResp, "application/json");
+ // Second is plain userInfo
+ queueMockServerResponse(mockOPServer, 200, userInfoResp, "application/json");
+ mockOPServer.start(9918);
+
+ final var prc = resumeBasicFlow();
+ mockOPServer.shutdown();
+
+ // Assert test conditions
+ assertFlowEndedInErrorConditions(prc, "InvalidToken");
+ }
+
+ /**
+ * Test a suitable error occurs if the id_token does not contain an audience.
+ *
+ * @throws Exception on error.
+ */
+ @Test
+ public void test_IDTokenHS256_NoAudience_PlainUserInfo() throws Exception {
+
+ basicSetup();
+
+ final MockWebServer mockOPServer = createSimpleServer();
+ final var accessTokenResp = TestTokenHelper.createAccessTokenResponseJSON(
+ Map.of("aud",List.of(""),"iss", OP_ISSUER_ID, "azp", CLIENT_ID),
+ JWSAlgorithm.HS256, null, null,
+ new DefaultClientSecretCredential(CLIENT_SECRET).toSigningCredential(), null);
+ final var userInfoResp =
+ TestTokenHelper.createPlainUserInfoResponseString(Map.of("iss", OP_ISSUER_ID, "aud", List.of(CLIENT_ID)));
+ // First is token exchange
+ queueMockServerResponse(mockOPServer, 200, accessTokenResp, "application/json");
+ // Second is plain userInfo
+ queueMockServerResponse(mockOPServer, 200, userInfoResp, "application/json");
+ mockOPServer.start(9918);
+
+ final var prc = resumeBasicFlow();
+ mockOPServer.shutdown();
+
+ // Assert test conditions
+ assertFlowEndedInErrorConditions(prc, "InvalidToken");
+ }
+
+ /**
+ * Test a suitable error occurs if the id_token does not contain an issued-at time.
+ *
+ * @throws Exception on error.
+ */
+ @Test
+ public void test_IDTokenHS256_NoIssuedAt_PlainUserInfo() throws Exception {
+
+ basicSetup();
+
+ final MockWebServer mockOPServer = createSimpleServer();
+ final Map<String, Object> iatOverride = new HashMap<>();
+ iatOverride.put("iat", null);
+ iatOverride.put("aud",List.of(CLIENT_ID));
+ iatOverride.put("iss", OP_ISSUER_ID);
+ iatOverride.put("azp", CLIENT_ID);
+ final var accessTokenResp = TestTokenHelper.createAccessTokenResponseJSON(iatOverride,
+ JWSAlgorithm.HS256, null, null,
+ new DefaultClientSecretCredential(CLIENT_SECRET).toSigningCredential(), null);
+ final var userInfoResp =
+ TestTokenHelper.createPlainUserInfoResponseString(Map.of("iss", OP_ISSUER_ID, "aud", List.of(CLIENT_ID)));
+ // First is token exchange
+ queueMockServerResponse(mockOPServer, 200, accessTokenResp, "application/json");
+ // Second is plain userInfo
+ queueMockServerResponse(mockOPServer, 200, userInfoResp, "application/json");
+ mockOPServer.start(9918);
+
+ final var prc = resumeBasicFlow();
+ mockOPServer.shutdown();
+
+ // Assert test conditions
+ assertFlowEndedInErrorConditions(prc, "InvalidToken");
+ }
+
+ /**
+ * Test a suitable error occurs if the id_token does not contain a valid nonce.
+ *
+ * @throws Exception on error.
+ */
+ @Test
+ public void test_IDTokenHS256_InvalidNonce_PlainUserInfo() throws Exception {
+
+ basicSetup();
+
+ final MockWebServer mockOPServer = createSimpleServer();
+ final var accessTokenResp = TestTokenHelper.createAccessTokenResponseJSON(Map.of("nonce", "WRONG",
+ "iss", OP_ISSUER_ID, "azp", CLIENT_ID, "aud", List.of(CLIENT_ID)),
+ JWSAlgorithm.HS256, null, null,
+ new DefaultClientSecretCredential(CLIENT_SECRET).toSigningCredential(), null);
+ final var userInfoResp =
+ TestTokenHelper.createPlainUserInfoResponseString(Map.of("iss", OP_ISSUER_ID, "aud", List.of(CLIENT_ID)));
+ // First is token exchange
+ queueMockServerResponse(mockOPServer, 200, accessTokenResp, "application/json");
+ // Second is plain userInfo
+ queueMockServerResponse(mockOPServer, 200, userInfoResp, "application/json");
+ mockOPServer.start(9918);
+
+ final var prc = resumeBasicFlow();
+ mockOPServer.shutdown();
+
+ // Assert test conditions
+ assertFlowEndedInErrorConditions(prc, "InvalidToken");
+ }
+
+ /**
+ * Test the flow from the external authorization request to the end of the flow.
+ * Using a MAC signed id_token and an invalid UserInfo JSON Response - it has no subject.
+ *
+ * @throws Exception on error.
+ */
+ @Test
+ public void test_IDTokenHS256_InvalidPlainUserInfo_NoSub() throws Exception {
+
+ basicSetup();
+
+ final MockWebServer mockOPServer = createSimpleServer();
+ final var accessTokenResp = TestTokenHelper.createAccessTokenResponseJSON(Map.of("iss", OP_ISSUER_ID, "azp",
+ CLIENT_ID, "aud", List.of(CLIENT_ID)), JWSAlgorithm.HS256, null, null,
+ new DefaultClientSecretCredential(CLIENT_SECRET).toSigningCredential(), null);
+ final var userInfoResp =
+ TestTokenHelper.createPlainUserInfoResponseString(
+ Map.of("sub","", "iss", OP_ISSUER_ID, "aud", List.of(CLIENT_ID)));
+
+ // First is token exchange
+ queueMockServerResponse(mockOPServer, 200, accessTokenResp, "application/json");
+ // Second is plain userInfo
+ queueMockServerResponse(mockOPServer, 200, userInfoResp, "application/json");
+
+ mockOPServer.start(9918);
+
+ final var prc = resumeBasicFlow();
+
+ mockOPServer.shutdown();
+
+ // Assert test conditions
+ // Should have failed to produce a result
+ assertFlowEndedInErrorConditions(prc, "InvalidUserInfoClaims");
+ }
}
diff --git a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/TestTokenHelper.java b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/TestTokenHelper.java
index 9a49ff8..8bc4547 100644
--- a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/TestTokenHelper.java
+++ b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/TestTokenHelper.java
@@ -25,6 +25,7 @@ import java.text.ParseException;
import java.time.Instant;
import java.util.Date;
import java.util.List;
+import java.util.Map;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -66,60 +67,83 @@ public final class TestTokenHelper {
/**
* Build a basic {@link JWTClaimsSet} from the supplied parameters.
*
- * @param opIssuerId the OP's issuer ID
- * @param clientId the client_id
- * @param audience the list of audiences
+ * @param overrideClaims claims to override
*
* @return the JWT claims set.
*/
- public static JWTClaimsSet createBasicClaims(
- final String opIssuerId, final String clientId,
- final List<String> audience) {
+ public static JWTClaimsSet createBasicClaims(final Map<String, Object> overrideClaims) {
return new JWTClaimsSet.Builder()
- .issuer(opIssuerId)
- .audience(audience)
- .subject("jdoe")
- .claim("preferred_username", "d.tu")
- .claim("given_name", "Demo")
- .claim("family_name", "User")
- .claim("nonce", "abadnonce")
- .claim("nickname", "Dee")
- .claim("azp", clientId)
- .claim("name","Demo T. User")
- .claim("acr","urn:mace:incommon:iap:silver")
- .claim("amr", List.of("pwd", "otp"))
- .claim("auth_time", new Date())
- .issueTime(new Date())
- .expirationTime(Date.from(Instant.now().plusSeconds(120)))
+ .issuer(getClaimValue(overrideClaims, "iss", "test-issuer", String.class))
+ .audience(getClaimValue(overrideClaims, "aud", List.of("test-client"), List.class))
+ .subject(getClaimValue(overrideClaims, "sub", "jdoe", String.class))
+ .claim("preferred_username", getClaimValue(overrideClaims, "preferred_username", "d.tu", String.class))
+ .claim("given_name", getClaimValue(overrideClaims, "given_name", "Demo", String.class))
+ .claim("family_name", getClaimValue(overrideClaims, "family_name", "User", String.class))
+ .claim("nonce", getClaimValue(overrideClaims, "nonce", "abadnonce", String.class))
+ .claim("nickname", getClaimValue(overrideClaims, "nickname", "Dee", String.class))
+ .claim("azp", getClaimValue(overrideClaims, "azp", "test-client", String.class))
+ .claim("name",getClaimValue(overrideClaims, "name", "Demo T. User", String.class))
+ .claim("acr",getClaimValue(overrideClaims, "acr", "urn:mace:incommon:iap:silver", String.class))
+ .claim("amr",getClaimValue(overrideClaims, "amr", List.of("pwd", "otp"), List.class))
+ .claim("auth_time", getClaimValue(overrideClaims, "auth_time", new Date(), Date.class))
+ .issueTime(getClaimValue(overrideClaims, "iat", new Date(), Date.class))
+ .expirationTime(getClaimValue(overrideClaims, "auth_time",
+ Date.from(Instant.now().plusSeconds(120)), Date.class))
.build();
}
/**
* Build a basic {@link JWTClaimsSet} from the supplied parameters to mock a UserInfo response.
*
- * @param opIssuerId the OP's issuer ID *
- * @param audience the list of audiences
- * @param sub the subject
+ * @param overrideClaims claims to override
*
* @return the JWT claims set.
*/
- public static JWTClaimsSet createBasicUserInfoClaims(final String opIssuerId, final List<String> audience,
- final String sub) {
+ public static JWTClaimsSet createBasicUserInfoClaims(final Map<String, Object> overrideClaims) {
return new JWTClaimsSet.Builder()
- .issuer(opIssuerId)
- .audience(audience)
- .subject(sub)
- .claim("preferred_username", "d.tu")
- .claim("given_name", "Demo")
- .claim("family_name", "User")
- .claim("nonce", "abadnonce")
- .claim("nickname", "Dee")
- .claim("name","Demo T. User")
+ .issuer(getClaimValue(overrideClaims, "iss", "test-issuer", String.class))
+ .audience(getClaimValue(overrideClaims, "aud", List.of("test-client"), List.class))
+ .subject(getClaimValue(overrideClaims, "sub", "jdoe", String.class))
+ .claim("preferred_username", getClaimValue(overrideClaims, "preferred_username", "d.tu", String.class))
+ .claim("given_name", getClaimValue(overrideClaims, "given_name", "Demo", String.class))
+ .claim("family_name", getClaimValue(overrideClaims, "family_name", "User", String.class))
+ .claim("nickname", getClaimValue(overrideClaims, "nickname", "Dee", String.class))
+ .claim("name",getClaimValue(overrideClaims, "name", "Demo T. User", String.class))
.build();
}
+ /**
+ * Extract any override from the overrides map, or return the default value if there is none.
+ *
+ * @param <T> the type to look for and return
+ * @param overrideClaims the overrides map
+ * @param claimName the claim name
+ * @param defaultValue the default value if no override is found
+ * @param type the type to return
+ *
+ * @return the override or the default value.
+ */
+ private static <T> T getClaimValue(final Map<String, Object> overrideClaims, final String claimName,
+ final Object defaultValue, final Class<T> type) {
+
+ if (overrideClaims.containsKey(claimName)) {
+ final Object override = overrideClaims.get(claimName);
+ if (override == null) {
+ return null;
+ }
+ if (type.isInstance(override)) {
+ //check empty string case, set null if so
+ if (override instanceof String && ((String)override).isEmpty()) {
+ return null;
+ }
+ return type.cast(override);
+ }
+ }
+ return type.cast(defaultValue);
+ }
+
/**
* Create a JWT from the given payload. The JWT can either be plain, or signed and encrypted. If encrypted, it must
* be signed.
@@ -189,35 +213,32 @@ public final class TestTokenHelper {
/**
* Create a JWT UserInfo response. Can be a JWS or JWE depending on the input values.
- *
- * @param opIssuerId the issuer
- * @param audience the audience
- * @param sub the subject
+ * @param overrideClaims claims to override
* @param sigAlg the signature algorithm
* @param jweAlg the encryption algorithm
* @param enc the content encryption algorithm
* @param sigKey the signing key
* @param encKey the encryption key
+ *
* @return
* @throws JOSEException on error
* @throws ParseException on error
*/
- public static JWT createJWTUserInfoResponse(final String opIssuerId, final List<String> audience,
- final String sub, @Nullable final JWSAlgorithm sigAlg,
- @Nullable final JWEAlgorithm jweAlg, @Nullable final EncryptionMethod enc,
- @Nullable final Credential sigKey, @Nullable final Credential encKey) throws JOSEException, ParseException {
+ public static JWT createJWTUserInfoResponse(final Map<String, Object> overrideClaims,
+ @Nullable final JWSAlgorithm sigAlg, @Nullable final JWEAlgorithm jweAlg,
+ @Nullable final EncryptionMethod enc, @Nullable final Credential sigKey, @Nullable final Credential encKey)
+ throws JOSEException, ParseException {
- final var payload = createBasicUserInfoClaims(opIssuerId, audience, sub);
+ final var payload = createBasicUserInfoClaims(overrideClaims);
return createJWT(payload, sigAlg, jweAlg, enc, sigKey, encKey);
}
/**
- * Create an access token response JSON object and build a suitable id_token to include in the response.
+ * Create an access token response JSON object and build a suitable id_token to include in the response. Any claim
+ * contained in the overrides list overrides the default value built by the basic claims method.
*
- * @param opIssuerId the issuer
- * @param clientId the client_id
- * @param audience the audience
+ * @param overrideClaims claims to override in the id_token
* @param sigAlg the signature algorithm
* @param jweAlg the encryption algorithm
* @param enc the content encryption algorithm
@@ -228,33 +249,31 @@ public final class TestTokenHelper {
*
* @throws Exception on error.
*/
- public static String createAccessTokenResponseJSON(
- final String opIssuerId, final String clientId,
- final List<String> audience, @Nullable final JWSAlgorithm sigAlg,
+ public static String createAccessTokenResponseJSON(final Map<String, Object> overrideClaims,
+ @Nullable final JWSAlgorithm sigAlg,
@Nullable final JWEAlgorithm jweAlg, @Nullable final EncryptionMethod enc,
@Nullable final Credential sigKey, @Nullable final Credential encKey) throws Exception {
- final var payload = createBasicClaims(opIssuerId, clientId, audience);
+ final var payload = createBasicClaims(overrideClaims);
final JWT idToken = createJWT(payload, sigAlg, jweAlg, enc, sigKey, encKey);
return buildTemplateAccessTokenJSONResponse(idToken.serialize());
}
+
/**
* Create a plain JSON object based UserInfo response.
*
- * @param opIssuerId the issuer
- * @param audience the audience
- * @param sub the subject.
+ * @param overrideClaims claims to override
+ *
* @return a plain JSON object representing the UserInfo response
*
* @throws JsonProcessingException on error
*/
- public static String createPlainUserInfoResponseString(final String opIssuerId, final List<String> audience,
- final String sub)
+ public static String createPlainUserInfoResponseString(final Map<String, Object> overrideClaims)
throws JsonProcessingException {
- final JWTClaimsSet claims = createBasicUserInfoClaims(opIssuerId, audience, sub);
+ final JWTClaimsSet claims = createBasicUserInfoClaims(overrideClaims);
return new ObjectMapper().writeValueAsString(claims.toJSONObject());
}
@@ -262,15 +281,16 @@ public final class TestTokenHelper {
/**
* Create a Plain UserInfo response JWT.
*
- * @param issuer the issuer
- * @param audience the audience
+ * @param overrideClaims claims to override
+ *
* @return the signed JWT
+ *
* @throws JOSEException on error
*/
- public static PlainJWT createPlainJWTUserInfoResponseJSON(final String issuer, final String audience)
+ public static PlainJWT createPlainJWTUserInfoResponseJSON(final Map<String, Object> overrideClaims)
throws JOSEException {
- final var payload = createBasicUserInfoClaims(issuer, List.of(audience), "jdoe");
+ final var payload = createBasicUserInfoClaims(overrideClaims);
return new PlainJWT(payload);
}
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list