[java-idp-oidc] 02/02: JOIDC-159 - JWT-based client authentication fails for token endpoint when using non-MDDriven config

Henri Mikkonen henri.mikkonen at iki.fi
Fri May 19 12:20:32 UTC 2023


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=cb029751bd31023eff23e5cc39bc1c0450a0afa8

commit cb029751bd31023eff23e5cc39bc1c0450a0afa8
Author: Henri Mikkonen <henri.mikkonen at iki.fi>
AuthorDate: Fri May 19 15:19:58 2023 +0300

    JOIDC-159 - JWT-based client authentication fails for token endpoint when using non-MDDriven config
    
    https://shibboleth.atlassian.net/browse/JOIDC-159
    
    - Use client ID 'mockClientIdNotMDDriven' for testing non-MDDriven configs
    - Run all JWT-based client authentication tests against non-MDDriven config too
      - They also keep on running with MDDriven configs as before
---
 .../AbstractOidcClientAuthenticationFlowTest.java  | 645 ++++++++++++---------
 .../flow/ClientCredentialsTokenFlowTest.java       |  33 +-
 .../op/profile/flow/IntrospectionFlowTest.java     |   6 +-
 .../oidc/op/profile/flow/RevocationFlowTest.java   |   6 +-
 .../plugin/oidc/op/profile/flow/TokenFlowTest.java |  15 +-
 .../src/test/resources/conf/relying-party.xml      |  11 +
 6 files changed, 429 insertions(+), 287 deletions(-)

diff --git a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/AbstractOidcClientAuthenticationFlowTest.java b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/AbstractOidcClientAuthenticationFlowTest.java
index 48177765..93ae585c 100644
--- a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/AbstractOidcClientAuthenticationFlowTest.java
+++ b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/AbstractOidcClientAuthenticationFlowTest.java
@@ -24,6 +24,7 @@ import java.security.PublicKey;
 import java.security.interfaces.RSAPrivateKey;
 import java.time.Instant;
 import java.util.Date;
+import java.util.List;
 import java.util.Map;
 
 import org.opensaml.profile.action.EventIds;
@@ -55,6 +56,7 @@ import net.shibboleth.utilities.java.support.collection.Pair;
 public abstract class AbstractOidcClientAuthenticationFlowTest extends AbstractOidcApiFlowTest {
     
     String clientId = "mockClientId";
+    String clientIdNotMDDriven = "mockClientIdNotMDDriven";
     String clientSecret = "mockClientSecretmockClientSecretmockClientSecretmockClientSecretmockClientSecret";
     String clientIdSaml = "mockSamlClientId";
     String clientSecretSaml = "mockClientSecretmockClientSecretmockClientSecret";
@@ -62,6 +64,8 @@ public abstract class AbstractOidcClientAuthenticationFlowTest extends AbstractO
     String jwtAud;
     String issuer = "https://op.example.org";
     
+    List<String> clientIds = List.of(clientId, clientIdNotMDDriven);
+    
     public AbstractOidcClientAuthenticationFlowTest(final String flowId) {
         super(flowId);
         jwtAud = "http://localhost/idp/profile/" + flowId;
@@ -80,475 +84,583 @@ public abstract class AbstractOidcClientAuthenticationFlowTest extends AbstractO
 
     @Test
     public void testInvalidSecretJWT_missingSub() throws Exception {
-        final SignedJWT jwt = createSecretJWT(claimsSetMissingSub(), clientSecret);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.HS256,
-                ClientAuthenticationMethod.CLIENT_SECRET_JWT);
-        assertErrorCode(result, "invalid_request");
-        assertErrorDescriptionContains(result, "UnableToDecode");
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createSecretJWT(claimsSetMissingSub(id), clientSecret);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.HS256,
+                    ClientAuthenticationMethod.CLIENT_SECRET_JWT);
+            assertErrorCode(result, "invalid_request");
+            assertErrorDescriptionContains(result, "UnableToDecode");
+        }
     }
 
     @Test
     public void testInvalidSecretJWT_missingIss() throws Exception {
-        final SignedJWT jwt = createSecretJWT(claimsSetMissingIss(), clientSecret);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.HS256,
-                ClientAuthenticationMethod.CLIENT_SECRET_JWT);
-        assertErrorCode(result, "invalid_request");
-        assertErrorDescriptionContains(result, "UnableToDecode");
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createSecretJWT(claimsSetMissingIss(id), clientSecret);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.HS256,
+                    ClientAuthenticationMethod.CLIENT_SECRET_JWT);
+            assertErrorCode(result, "invalid_request");
+            assertErrorDescriptionContains(result, "UnableToDecode");
+        }
     }
 
     @Test
     public void testInvalidSecretJWT_missingAud() throws Exception {
-        final SignedJWT jwt = createSecretJWT(claimsSetMissingAud(), clientSecret);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.HS256,
-                ClientAuthenticationMethod.CLIENT_SECRET_JWT);
-        assertErrorCode(result, "invalid_request");
-        assertErrorDescriptionContains(result, "UnableToDecode");
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createSecretJWT(claimsSetMissingAud(id), clientSecret);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.HS256,
+                    ClientAuthenticationMethod.CLIENT_SECRET_JWT);
+            assertErrorCode(result, "invalid_request");
+            assertErrorDescriptionContains(result, "UnableToDecode");
+        }
     }
 
     @Test
     public void testInvalidSecretJWT_missingExp() throws Exception {
-        final SignedJWT jwt = createSecretJWT(claimsSetMissingExp(), clientSecret);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.HS256,
-                ClientAuthenticationMethod.CLIENT_SECRET_JWT);
-        assertErrorCode(result, "invalid_request");
-        assertErrorDescriptionContains(result, "UnableToDecode");
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createSecretJWT(claimsSetMissingExp(id), clientSecret);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.HS256,
+                    ClientAuthenticationMethod.CLIENT_SECRET_JWT);
+            assertErrorCode(result, "invalid_request");
+            assertErrorDescriptionContains(result, "UnableToDecode");
+        }
     }
 
     @Test
     public void testInvalidSecretJWT_expiredExp() throws Exception {
-        final SignedJWT jwt = createSecretJWT(claimsSetExpiredExp(), clientSecret);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.HS256,
-                ClientAuthenticationMethod.CLIENT_SECRET_JWT);
-        assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
-        assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createSecretJWT(claimsSetExpiredExp(id), clientSecret);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.HS256,
+                    ClientAuthenticationMethod.CLIENT_SECRET_JWT);
+            assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
+            assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        }
     }
 
     @Test
     public void testInvalidSecretJWT_issuedInTheFuture() throws Exception {
-        final SignedJWT jwt = createSecretJWT(claimsSetIssuedInTheFuture(), clientSecret);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.HS256,
-                ClientAuthenticationMethod.CLIENT_SECRET_JWT);
-        assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
-        assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createSecretJWT(claimsSetIssuedInTheFuture(id), clientSecret);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.HS256,
+                    ClientAuthenticationMethod.CLIENT_SECRET_JWT);
+            assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
+            assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        }
     }
 
     @Test
     public void testInvalidSecretJWT_missingJti() throws Exception {
-        final SignedJWT jwt = createSecretJWT(claimsSetMissingJti(), clientSecret);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.HS256,
-                ClientAuthenticationMethod.CLIENT_SECRET_JWT);
-        assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
-        assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createSecretJWT(claimsSetMissingJti(id), clientSecret);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.HS256,
+                    ClientAuthenticationMethod.CLIENT_SECRET_JWT);
+            assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
+            assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        }
     }
 
     @Test
     public void testInvalidSecretJWT_replayJti() throws Exception {
-        final SignedJWT jwt = createSecretJWT(validClaimsSet(), clientSecret);
-        launchWithJwtAuthentication(jwt, JWSAlgorithm.HS256, ClientAuthenticationMethod.CLIENT_SECRET_JWT);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.HS256,
-                ClientAuthenticationMethod.CLIENT_SECRET_JWT);
-        assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
-        assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createSecretJWT(validClaimsSet(id), clientSecret);
+            launchWithJwtAuthentication(jwt, JWSAlgorithm.HS256, ClientAuthenticationMethod.CLIENT_SECRET_JWT);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.HS256,
+                    ClientAuthenticationMethod.CLIENT_SECRET_JWT);
+            assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
+            assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        }
     }
 
     @Test
     public void testInvalidSecretJWT_invalidSecret() throws Exception {
-        final SignedJWT jwt = createSecretJWT(validClaimsSet(), clientSecret + "wrong");
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.HS256,
-                ClientAuthenticationMethod.CLIENT_SECRET_JWT);
-        assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
-        assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createSecretJWT(validClaimsSet(id), clientSecret + "wrong");
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.HS256,
+                    ClientAuthenticationMethod.CLIENT_SECRET_JWT);
+            assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
+            assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        }
     }
 
     @Test
     public void testValidSecretJWTHS256_TokenEndpointAudience() throws Exception {
-        final SignedJWT jwt = createSecretJWT(validClaimsSet("http://localhost/idp/profile/oidc/token"), clientSecret, JWSAlgorithm.HS256);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, null,
-                ClientAuthenticationMethod.CLIENT_SECRET_JWT);
-        assertSuccessResponse(result);
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createSecretJWT(validClaimsSet(id, "http://localhost/idp/profile/oidc/token"),
+                    clientSecret, JWSAlgorithm.HS256);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, null,
+                    ClientAuthenticationMethod.CLIENT_SECRET_JWT);
+            assertSuccessResponse(result, id);
+        }
     }
 
     @Test
     public void testValidSecretJWTHS256_IssuerAudience() throws Exception {
-        final SignedJWT jwt = createSecretJWT(validClaimsSet(issuer), clientSecret, JWSAlgorithm.HS256);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, null,
-                ClientAuthenticationMethod.CLIENT_SECRET_JWT);
-        assertSuccessResponse(result);
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createSecretJWT(validClaimsSet(id, issuer), clientSecret, JWSAlgorithm.HS256);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, null,
+                    ClientAuthenticationMethod.CLIENT_SECRET_JWT);
+            assertSuccessResponse(result, id);
+        }
     }
 
     @Test
     public void testValidSecretJWTHS256_noRegisteredAlg() throws Exception {
-        final SignedJWT jwt = createSecretJWT(validClaimsSet(), clientSecret, JWSAlgorithm.HS256);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, null,
-                ClientAuthenticationMethod.CLIENT_SECRET_JWT);
-        assertSuccessResponse(result);
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createSecretJWT(validClaimsSet(id), clientSecret, JWSAlgorithm.HS256);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, null,
+                    ClientAuthenticationMethod.CLIENT_SECRET_JWT);
+            assertSuccessResponse(result, id);
+        }
     }
 
     @Test
     public void testValidSecretJWTHS256_HS256Registered() throws Exception {
-        final SignedJWT jwt = createSecretJWT(validClaimsSet(), clientSecret, JWSAlgorithm.HS256);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.HS256,
-                ClientAuthenticationMethod.CLIENT_SECRET_JWT);
-        assertSuccessResponse(result);
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createSecretJWT(validClaimsSet(id), clientSecret, JWSAlgorithm.HS256);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.HS256,
+                    ClientAuthenticationMethod.CLIENT_SECRET_JWT);
+            assertSuccessResponse(result, id);
+        }
     }
 
     @Test
     public void testValidSecretJWTH384_noRegisteredAlg() throws Exception {
-        final SignedJWT jwt = createSecretJWT(validClaimsSet(), clientSecret, JWSAlgorithm.HS384);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, null,
-                ClientAuthenticationMethod.CLIENT_SECRET_JWT);
-        assertSuccessResponse(result);
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createSecretJWT(validClaimsSet(id), clientSecret, JWSAlgorithm.HS384);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, null,
+                    ClientAuthenticationMethod.CLIENT_SECRET_JWT);
+            assertSuccessResponse(result, id);
+        }
     }
 
     @Test
     public void testValidSecretJWTHS384_HS384Registered() throws Exception {
-        final SignedJWT jwt = createSecretJWT(validClaimsSet(), clientSecret, JWSAlgorithm.HS384);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.HS384,
-                ClientAuthenticationMethod.CLIENT_SECRET_JWT);
-        assertSuccessResponse(result);
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createSecretJWT(validClaimsSet(id), clientSecret, JWSAlgorithm.HS384);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.HS384,
+                    ClientAuthenticationMethod.CLIENT_SECRET_JWT);
+            assertSuccessResponse(result, id);
+        }
     }
 
     @Test
     public void testValidSecretJWTHS512_noRegisteredAlg() throws Exception {
-        final SignedJWT jwt = createSecretJWT(validClaimsSet(), clientSecret, JWSAlgorithm.HS512);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, null,
-                ClientAuthenticationMethod.CLIENT_SECRET_JWT);
-        assertSuccessResponse(result);
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createSecretJWT(validClaimsSet(id), clientSecret, JWSAlgorithm.HS512);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, null,
+                    ClientAuthenticationMethod.CLIENT_SECRET_JWT);
+            assertSuccessResponse(result, id);
+        }
     }
 
     @Test
     public void testValidSecretJWTHS512_HS512Registered() throws Exception {
-        final SignedJWT jwt = createSecretJWT(validClaimsSet(), clientSecret, JWSAlgorithm.HS512);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.HS512,
-                ClientAuthenticationMethod.CLIENT_SECRET_JWT);
-        assertSuccessResponse(result);
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createSecretJWT(validClaimsSet(id), clientSecret, JWSAlgorithm.HS512);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.HS512,
+                    ClientAuthenticationMethod.CLIENT_SECRET_JWT);
+            assertSuccessResponse(result, id);
+        }
     }
 
     @Test
     public void testInvalidSecretJWTHS256_algNotMatchingRegistered() throws Exception {
-        final SignedJWT jwt = createSecretJWT(validClaimsSet(), clientSecret, JWSAlgorithm.HS256);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.HS512,
-                ClientAuthenticationMethod.CLIENT_SECRET_JWT);
-        assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
-        assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createSecretJWT(validClaimsSet(id), clientSecret, JWSAlgorithm.HS256);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.HS512,
+                    ClientAuthenticationMethod.CLIENT_SECRET_JWT);
+            assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
+            assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        }
     }
 
     @Test
     public void testInvalidSecretJWTHS384_algNotMatchingRegistered() throws Exception {
-        final SignedJWT jwt = createSecretJWT(validClaimsSet(), clientSecret, JWSAlgorithm.HS384);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.HS512,
-                ClientAuthenticationMethod.CLIENT_SECRET_JWT);
-        assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
-        assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createSecretJWT(validClaimsSet(id), clientSecret, JWSAlgorithm.HS384);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.HS512,
+                    ClientAuthenticationMethod.CLIENT_SECRET_JWT);
+            assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
+            assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        }
     }
 
     @Test
     public void testInvalidSecretJWTHS512_algNotMatchingRegistered() throws Exception {
-        final SignedJWT jwt = createSecretJWT(validClaimsSet(), clientSecret, JWSAlgorithm.HS512);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.HS384,
-                ClientAuthenticationMethod.CLIENT_SECRET_JWT);
-        assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
-        assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createSecretJWT(validClaimsSet(id), clientSecret, JWSAlgorithm.HS512);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.HS384,
+                    ClientAuthenticationMethod.CLIENT_SECRET_JWT);
+            assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
+            assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        }
     }
 
     @Test
     public void testInvalidPrivateKeyJWT_missingSub() throws Exception {
-        final SignedJWT jwt = createPrivateKeyJWT(claimsSetMissingSub(), rsaPrivateKey);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.RS256,
-                ClientAuthenticationMethod.PRIVATE_KEY_JWT, rsaPublicKey);
-        assertErrorCode(result, "invalid_request");
-        assertErrorDescriptionContains(result, "UnableToDecode");
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createPrivateKeyJWT(claimsSetMissingSub(id), rsaPrivateKey);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.RS256,
+                    ClientAuthenticationMethod.PRIVATE_KEY_JWT, rsaPublicKey);
+            assertErrorCode(result, "invalid_request");
+            assertErrorDescriptionContains(result, "UnableToDecode");
+        }
     }
 
     @Test
     public void testInvalidPrivateKeyJWT_missingIss() throws Exception {
-        final SignedJWT jwt = createPrivateKeyJWT(claimsSetMissingIss(), rsaPrivateKey);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.RS256,
-                ClientAuthenticationMethod.PRIVATE_KEY_JWT, rsaPublicKey);
-        assertErrorCode(result, "invalid_request");
-        assertErrorDescriptionContains(result, "UnableToDecode");
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createPrivateKeyJWT(claimsSetMissingIss(id), rsaPrivateKey);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.RS256,
+                    ClientAuthenticationMethod.PRIVATE_KEY_JWT, rsaPublicKey);
+            assertErrorCode(result, "invalid_request");
+            assertErrorDescriptionContains(result, "UnableToDecode");
+        }
     }
 
     @Test
     public void testInvalidPrivateKeyJWT_missingAud() throws Exception {
-        final SignedJWT jwt = createPrivateKeyJWT(claimsSetMissingAud(), rsaPrivateKey);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.RS256,
-                ClientAuthenticationMethod.PRIVATE_KEY_JWT, rsaPublicKey);
-        assertErrorCode(result, "invalid_request");
-        assertErrorDescriptionContains(result, "UnableToDecode");
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createPrivateKeyJWT(claimsSetMissingAud(id), rsaPrivateKey);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.RS256,
+                    ClientAuthenticationMethod.PRIVATE_KEY_JWT, rsaPublicKey);
+            assertErrorCode(result, "invalid_request");
+            assertErrorDescriptionContains(result, "UnableToDecode");
+        }
     }
 
     @Test
     public void testInvalidPrivateKeyJWT_missingExp() throws Exception {
-        final SignedJWT jwt = createPrivateKeyJWT(claimsSetMissingExp(), rsaPrivateKey);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.RS256,
-                ClientAuthenticationMethod.PRIVATE_KEY_JWT, rsaPublicKey);
-        assertErrorCode(result, "invalid_request");
-        assertErrorDescriptionContains(result, "UnableToDecode");
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createPrivateKeyJWT(claimsSetMissingExp(id), rsaPrivateKey);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.RS256,
+                    ClientAuthenticationMethod.PRIVATE_KEY_JWT, rsaPublicKey);
+            assertErrorCode(result, "invalid_request");
+            assertErrorDescriptionContains(result, "UnableToDecode");
+        }
     }
 
     @Test
     public void testInvalidPrivateKeyJWT_expiredExp() throws Exception {
-        final SignedJWT jwt = createPrivateKeyJWT(claimsSetExpiredExp(), rsaPrivateKey);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.RS256,
-                ClientAuthenticationMethod.PRIVATE_KEY_JWT, rsaPublicKey);
-        assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
-        assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createPrivateKeyJWT(claimsSetExpiredExp(id), rsaPrivateKey);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.RS256,
+                    ClientAuthenticationMethod.PRIVATE_KEY_JWT, rsaPublicKey);
+            assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
+            assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        }
     }
 
     @Test
     public void testInvalidPrivateKeyJWT_issuedInTheFuture() throws Exception {
-        final SignedJWT jwt = createPrivateKeyJWT(claimsSetIssuedInTheFuture(), rsaPrivateKey);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.RS256,
-                ClientAuthenticationMethod.PRIVATE_KEY_JWT, rsaPublicKey);
-        assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
-        assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createPrivateKeyJWT(claimsSetIssuedInTheFuture(id), rsaPrivateKey);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.RS256,
+                    ClientAuthenticationMethod.PRIVATE_KEY_JWT, rsaPublicKey);
+            assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
+            assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        }
     }
 
     @Test
     public void testInvalidPrivateKeyJWT_missingJti() throws Exception {
-        final SignedJWT jwt = createPrivateKeyJWT(claimsSetMissingJti(), rsaPrivateKey);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.RS256,
-                ClientAuthenticationMethod.PRIVATE_KEY_JWT, rsaPublicKey);
-        assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
-        assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createPrivateKeyJWT(claimsSetMissingJti(id), rsaPrivateKey);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.RS256,
+                    ClientAuthenticationMethod.PRIVATE_KEY_JWT, rsaPublicKey);
+            assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
+            assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        }
     }
 
     @Test
     public void testInvalidPrivateKeyJWT_replayJti() throws Exception {
-        final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(), rsaPrivateKey);
-        launchWithJwtAuthentication(jwt, JWSAlgorithm.RS256, ClientAuthenticationMethod.PRIVATE_KEY_JWT);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.RS256,
-                ClientAuthenticationMethod.PRIVATE_KEY_JWT, rsaPublicKey);
-        assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
-        assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(id), rsaPrivateKey);
+            launchWithJwtAuthentication(jwt, JWSAlgorithm.RS256, ClientAuthenticationMethod.PRIVATE_KEY_JWT);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.RS256,
+                    ClientAuthenticationMethod.PRIVATE_KEY_JWT, rsaPublicKey);
+            assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
+            assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        }
     }
 
     @Test
     public void testInvalidPrivateKeyRSJWT_invalidSignerKey() throws Exception {
-        final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(), (RSAPrivateKey)generateNewKeyPair().getPrivate());
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.RS256,
-                ClientAuthenticationMethod.PRIVATE_KEY_JWT, rsaPublicKey);
-        assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
-        assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(id),
+                    (RSAPrivateKey)generateNewKeyPair().getPrivate());
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.RS256,
+                    ClientAuthenticationMethod.PRIVATE_KEY_JWT, rsaPublicKey);
+            assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
+            assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        }
     }
 
     @Test
     public void testInvalidPrivateKeyRSJWT_noTrustedKey() throws Exception {
-        final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(), rsaPrivateKey);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.RS256,
-                ClientAuthenticationMethod.PRIVATE_KEY_JWT);
-        assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
-        assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(id), rsaPrivateKey);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.RS256,
+                    ClientAuthenticationMethod.PRIVATE_KEY_JWT);
+            assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
+            assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        }
     }
 
     @Test
     public void testInvalidPrivateKeyRSJWT_wrongKey() throws Exception {
-        final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(), rsaPrivateKey);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.RS256,
-                ClientAuthenticationMethod.PRIVATE_KEY_JWT, super.generateNewKeyPair().getPublic());
-        assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
-        assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(id), rsaPrivateKey);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.RS256,
+                    ClientAuthenticationMethod.PRIVATE_KEY_JWT, super.generateNewKeyPair().getPublic());
+            assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
+            assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        }
     }
 
     @Test
     public void testValidPrivateKeyJWTRS256_noRegisteredAlg() throws Exception {
-        final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(), rsaPrivateKey, JWSAlgorithm.RS256);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, null,
-                ClientAuthenticationMethod.PRIVATE_KEY_JWT, rsaPublicKey);
-        assertSuccessResponse(result);
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(id), rsaPrivateKey, JWSAlgorithm.RS256);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, null,
+                    ClientAuthenticationMethod.PRIVATE_KEY_JWT, rsaPublicKey);
+            assertSuccessResponse(result, id);
+        }
     }
 
     @Test
     public void testValidPrivateKeyJWTRS256_RS256Registered() throws Exception {
-        final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(), rsaPrivateKey, JWSAlgorithm.RS256);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.RS256,
-                ClientAuthenticationMethod.PRIVATE_KEY_JWT, rsaPublicKey);
-        assertSuccessResponse(result);
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(id), rsaPrivateKey, JWSAlgorithm.RS256);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.RS256,
+                    ClientAuthenticationMethod.PRIVATE_KEY_JWT, rsaPublicKey);
+            assertSuccessResponse(result, id);
+        }
     }
 
     @Test
     public void testValidPrivateKeyJWTRS384_noRegisteredAlg() throws Exception {
-        final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(), rsaPrivateKey, JWSAlgorithm.RS384);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, null,
-                ClientAuthenticationMethod.PRIVATE_KEY_JWT, rsaPublicKey);
-        assertSuccessResponse(result);
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(id), rsaPrivateKey, JWSAlgorithm.RS384);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, null,
+                    ClientAuthenticationMethod.PRIVATE_KEY_JWT, rsaPublicKey);
+            assertSuccessResponse(result, id);
+        }
     }
 
     @Test
     public void testValidPrivateKeyJWTRS384_RS384Registered() throws Exception {
-        final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(), rsaPrivateKey, JWSAlgorithm.RS384);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.RS384,
-                ClientAuthenticationMethod.PRIVATE_KEY_JWT, rsaPublicKey);
-        assertSuccessResponse(result);
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(id), rsaPrivateKey, JWSAlgorithm.RS384);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.RS384,
+                    ClientAuthenticationMethod.PRIVATE_KEY_JWT, rsaPublicKey);
+            assertSuccessResponse(result, id);
+        }
     }
 
     @Test
     public void testValidPrivateKeyJWTRS512_noRegisteredAlg() throws Exception {
-        final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(), rsaPrivateKey, JWSAlgorithm.RS512);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, null,
-                ClientAuthenticationMethod.PRIVATE_KEY_JWT, rsaPublicKey);
-        assertSuccessResponse(result);
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(id), rsaPrivateKey, JWSAlgorithm.RS512);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, null,
+                    ClientAuthenticationMethod.PRIVATE_KEY_JWT, rsaPublicKey);
+            assertSuccessResponse(result, id);
+        }
     }
 
     @Test
     public void testValidPrivateKeyJWTRS512_RS512Registered() throws Exception {
-        final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(), rsaPrivateKey, JWSAlgorithm.RS512);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.RS512,
-                ClientAuthenticationMethod.PRIVATE_KEY_JWT, rsaPublicKey);
-        assertSuccessResponse(result);
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(id), rsaPrivateKey, JWSAlgorithm.RS512);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.RS512,
+                    ClientAuthenticationMethod.PRIVATE_KEY_JWT, rsaPublicKey);
+            assertSuccessResponse(result, id);
+        }
     }
 
     @Test
     public void testInvalidPrivateKeyJWTRS256_algNotMatchingRegistered() throws Exception {
-        final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(), rsaPrivateKey, JWSAlgorithm.RS256);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.RS512,
-                ClientAuthenticationMethod.PRIVATE_KEY_JWT, rsaPublicKey);
-        assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
-        assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(id), rsaPrivateKey, JWSAlgorithm.RS256);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.RS512,
+                    ClientAuthenticationMethod.PRIVATE_KEY_JWT, rsaPublicKey);
+            assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
+            assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        }
     }
 
     @Test
     public void testInvalidPrivateKeyJWTRS384_algNotMatchingRegistered() throws Exception {
-        final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(), rsaPrivateKey, JWSAlgorithm.RS384);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.RS512,
-                ClientAuthenticationMethod.PRIVATE_KEY_JWT, rsaPublicKey);
-        assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
-        assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(id), rsaPrivateKey, JWSAlgorithm.RS384);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.RS512,
+                    ClientAuthenticationMethod.PRIVATE_KEY_JWT, rsaPublicKey);
+            assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
+            assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        }
     }
 
     @Test
     public void testInvalidPrivateKeyJWTRS512_algNotMatchingRegistered() throws Exception {
-        final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(), rsaPrivateKey, JWSAlgorithm.RS512);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.RS384,
-                ClientAuthenticationMethod.PRIVATE_KEY_JWT, rsaPublicKey);
-        assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
-        assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(id), rsaPrivateKey, JWSAlgorithm.RS512);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.RS384,
+                    ClientAuthenticationMethod.PRIVATE_KEY_JWT, rsaPublicKey);
+            assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
+            assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        }
     }
 
     @Test
     public void testInvalidPrivateKeyESJWT_invalidSignerKey() throws Exception {
-        final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(),
-                initializeECKey(Curve.P_256, "mock").toECPrivateKey(), JWSAlgorithm.ES256);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.ES256,
-                ClientAuthenticationMethod.PRIVATE_KEY_JWT, ecKey.toECPublicKey());
-        assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
-        assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(id),
+                    initializeECKey(Curve.P_256, "mock").toECPrivateKey(), JWSAlgorithm.ES256);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.ES256,
+                    ClientAuthenticationMethod.PRIVATE_KEY_JWT, ecKey.toECPublicKey());
+            assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
+            assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        }
     }
 
     @Test
     public void testInvalidPrivateKeyESJWT_noTrustedKey() throws Exception {
-        final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(), ecKey.toECPrivateKey(), JWSAlgorithm.ES256);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.ES256,
-                ClientAuthenticationMethod.PRIVATE_KEY_JWT);
-        assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
-        assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(id), ecKey.toECPrivateKey(), JWSAlgorithm.ES256);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.ES256,
+                    ClientAuthenticationMethod.PRIVATE_KEY_JWT);
+            assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
+            assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        }
     }
 
     @Test
     public void testInvalidPrivateKeyESJWT_wrongKey() throws Exception {
-        final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(), ecKey.toECPrivateKey(), JWSAlgorithm.ES256);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.ES384,
-                ClientAuthenticationMethod.PRIVATE_KEY_JWT, initializeECKey(Curve.P_384, "mock").toECPublicKey());
-        assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
-        assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(id), ecKey.toECPrivateKey(), JWSAlgorithm.ES256);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.ES384,
+                    ClientAuthenticationMethod.PRIVATE_KEY_JWT, initializeECKey(Curve.P_384, "mock").toECPublicKey());
+            assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
+            assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        }
     }
 
     @Test
     public void testValidPrivateKeyJWTES256_noRegisteredAlg() throws Exception {
-        final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(), ecKey.toECPrivateKey(), JWSAlgorithm.ES256);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, null,
-                ClientAuthenticationMethod.PRIVATE_KEY_JWT, ecKey.toECPublicKey());
-        assertSuccessResponse(result);
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(id), ecKey.toECPrivateKey(), JWSAlgorithm.ES256);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, null,
+                    ClientAuthenticationMethod.PRIVATE_KEY_JWT, ecKey.toECPublicKey());
+            assertSuccessResponse(result, id);
+        }
     }
 
     @Test
     public void testValidPrivateKeyJWTES256_ES256Registered() throws Exception {
-        final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(), ecKey.toECPrivateKey(), JWSAlgorithm.ES256);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.ES256,
-                ClientAuthenticationMethod.PRIVATE_KEY_JWT, ecKey.toECPublicKey());
-        assertSuccessResponse(result);
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(id), ecKey.toECPrivateKey(), JWSAlgorithm.ES256);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.ES256,
+                    ClientAuthenticationMethod.PRIVATE_KEY_JWT, ecKey.toECPublicKey());
+            assertSuccessResponse(result, id);
+        }
     }
 
     @Test
     public void testValidPrivateKeyJWTES384_noRegisteredAlg() throws Exception {
         final ECKey ecKey = initializeECKey(Curve.P_384, "384");
-        final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(), ecKey.toECPrivateKey(), JWSAlgorithm.ES384);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, null,
-                ClientAuthenticationMethod.PRIVATE_KEY_JWT, ecKey.toECPublicKey());
-        // ES-384 excluded in the test relying-party config
-        assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
-        assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(id), ecKey.toECPrivateKey(), JWSAlgorithm.ES384);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, null,
+                    ClientAuthenticationMethod.PRIVATE_KEY_JWT, ecKey.toECPublicKey());
+            // ES-384 excluded in the test relying-party config
+            assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
+            assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        }
     }
 
     @Test
     public void testValidPrivateKeyJWTES384_ES384Registered() throws Exception {
         final ECKey ecKey = initializeECKey(Curve.P_384, "384");
-        final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(), ecKey.toECPrivateKey(), JWSAlgorithm.ES384);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.ES384,
-                ClientAuthenticationMethod.PRIVATE_KEY_JWT, ecKey.toECPublicKey());
-        // ES-384 excluded in the test relying-party config
-        assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
-        assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(id), ecKey.toECPrivateKey(), JWSAlgorithm.ES384);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.ES384,
+                    ClientAuthenticationMethod.PRIVATE_KEY_JWT, ecKey.toECPublicKey());
+            // ES-384 excluded in the test relying-party config
+            assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
+            assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        }
     }
 
     @Test
     public void testValidPrivateKeyJWTES512_noRegisteredAlg() throws Exception {
         final ECKey ecKey = initializeECKey(Curve.P_521, "521");
-        final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(), ecKey.toECPrivateKey(), JWSAlgorithm.ES512);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, null,
-                ClientAuthenticationMethod.PRIVATE_KEY_JWT, ecKey.toECPublicKey());
-        assertSuccessResponse(result);
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(id), ecKey.toECPrivateKey(), JWSAlgorithm.ES512);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, null,
+                    ClientAuthenticationMethod.PRIVATE_KEY_JWT, ecKey.toECPublicKey());
+            assertSuccessResponse(result, id);
+        }
     }
 
     @Test
     public void testValidPrivateKeyJWTES512_ES512Registered() throws Exception {
         final ECKey ecKey = initializeECKey(Curve.P_521, "521");
-        final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(), ecKey.toECPrivateKey(), JWSAlgorithm.ES512);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.ES512,
-                ClientAuthenticationMethod.PRIVATE_KEY_JWT, ecKey.toECPublicKey());
-        assertSuccessResponse(result);
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(id), ecKey.toECPrivateKey(), JWSAlgorithm.ES512);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.ES512,
+                    ClientAuthenticationMethod.PRIVATE_KEY_JWT, ecKey.toECPublicKey());
+            assertSuccessResponse(result, id);
+        }
     }
 
     @Test
     public void testInvalidPrivateKeyJWTES256_algNotMatchingRegistered() throws Exception {
-        final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(), ecKey.toECPrivateKey(), JWSAlgorithm.ES256);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.ES512,
-                ClientAuthenticationMethod.PRIVATE_KEY_JWT, ecKey.toECPublicKey());
-        assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
-        assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(id), ecKey.toECPrivateKey(), JWSAlgorithm.ES256);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.ES512,
+                    ClientAuthenticationMethod.PRIVATE_KEY_JWT, ecKey.toECPublicKey());
+            assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
+            assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        }
     }
 
     @Test
     public void testInvalidPrivateKeyJWTES384_algNotMatchingRegistered() throws Exception {
         final ECKey ecKey = initializeECKey(Curve.P_384, "384");
-        final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(), ecKey.toECPrivateKey(), JWSAlgorithm.ES384);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.ES512,
-                ClientAuthenticationMethod.PRIVATE_KEY_JWT, ecKey.toECPublicKey());
-        assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
-        assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(id), ecKey.toECPrivateKey(), JWSAlgorithm.ES384);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.ES512,
+                    ClientAuthenticationMethod.PRIVATE_KEY_JWT, ecKey.toECPublicKey());
+            assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
+            assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        }
     }
 
     @Test
     public void testInvalidPrivateKeyJWTES512_algNotMatchingRegistered() throws Exception {
         final ECKey ecKey = initializeECKey(Curve.P_521, "521");
-        final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(), ecKey.toECPrivateKey(), JWSAlgorithm.ES512);
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.ES384,
-                ClientAuthenticationMethod.PRIVATE_KEY_JWT, ecKey.toECPublicKey());
-        assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
-        assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        for (final String id : clientIds) {
+            final SignedJWT jwt = createPrivateKeyJWT(validClaimsSet(id), ecKey.toECPrivateKey(), JWSAlgorithm.ES512);
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.ES384,
+                    ClientAuthenticationMethod.PRIVATE_KEY_JWT, ecKey.toECPublicKey());
+            assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
+            assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+        }
     }
 
     @Test
     public void testPlainJWT() throws Exception {
-        final PlainJWT jwt = new PlainJWT(validClaimsSet());
-        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.RS256,
-                ClientAuthenticationMethod.PRIVATE_KEY_JWT);
-        assertErrorCode(result, "invalid_request");
-        assertErrorDescriptionContains(result, "UnableToDecode");
+        for (final String id : clientIds) {
+            final PlainJWT jwt = new PlainJWT(validClaimsSet(id));
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.RS256,
+                    ClientAuthenticationMethod.PRIVATE_KEY_JWT);
+            assertErrorCode(result, "invalid_request");
+            assertErrorDescriptionContains(result, "UnableToDecode");
+        }
     }
 
-    protected JWTClaimsSet claimsSetMissingSub() {
+    protected JWTClaimsSet claimsSetMissingSub(final String clientId) {
         return new JWTClaimsSet.Builder()
                 .issuer(clientId)
                 .audience(jwtAud)
@@ -557,7 +669,7 @@ public abstract class AbstractOidcClientAuthenticationFlowTest extends AbstractO
                 .build();
     }
     
-    protected JWTClaimsSet claimsSetMissingIss() {
+    protected JWTClaimsSet claimsSetMissingIss(final String clientId) {
         return new JWTClaimsSet.Builder()
                 .subject(clientId)
                 .audience(jwtAud)
@@ -566,7 +678,7 @@ public abstract class AbstractOidcClientAuthenticationFlowTest extends AbstractO
                 .build();
     }
     
-    protected JWTClaimsSet claimsSetMissingAud() {
+    protected JWTClaimsSet claimsSetMissingAud(final String clientId) {
         return new JWTClaimsSet.Builder()
                 .subject(clientId)
                 .issuer(clientId)
@@ -575,7 +687,7 @@ public abstract class AbstractOidcClientAuthenticationFlowTest extends AbstractO
                 .build();
     }
     
-    protected JWTClaimsSet claimsSetMissingExp() {
+    protected JWTClaimsSet claimsSetMissingExp(final String clientId) {
         return new JWTClaimsSet.Builder()
                 .subject(clientId)
                 .issuer(clientId)
@@ -584,7 +696,7 @@ public abstract class AbstractOidcClientAuthenticationFlowTest extends AbstractO
                 .build();
     }
     
-    protected JWTClaimsSet claimsSetExpiredExp() {
+    protected JWTClaimsSet claimsSetExpiredExp(final String clientId) {
         return new JWTClaimsSet.Builder()
                 .subject(clientId)
                 .issuer(clientId)
@@ -594,7 +706,7 @@ public abstract class AbstractOidcClientAuthenticationFlowTest extends AbstractO
                 .build();
     }
     
-    protected JWTClaimsSet claimsSetIssuedInTheFuture() {
+    protected JWTClaimsSet claimsSetIssuedInTheFuture(final String clientId) {
         return new JWTClaimsSet.Builder()
                 .subject(clientId)
                 .issuer(clientId)
@@ -605,7 +717,7 @@ public abstract class AbstractOidcClientAuthenticationFlowTest extends AbstractO
                 .build();
     }
     
-    protected JWTClaimsSet claimsSetMissingJti() {
+    protected JWTClaimsSet claimsSetMissingJti(final String clientId) {
         return new JWTClaimsSet.Builder()
                 .subject(clientId)
                 .issuer(clientId)
@@ -614,11 +726,11 @@ public abstract class AbstractOidcClientAuthenticationFlowTest extends AbstractO
                 .build();
     }
 
-    protected JWTClaimsSet validClaimsSet() {
-        return validClaimsSet(jwtAud);
+    protected JWTClaimsSet validClaimsSet(final String clientId) {
+        return validClaimsSet(clientId, jwtAud);
     }
 
-    protected JWTClaimsSet validClaimsSet(final String audience) {
+    protected JWTClaimsSet validClaimsSet(final String clientId, final String audience) {
         return new JWTClaimsSet.Builder()
                 .subject(clientId)
                 .issuer(clientId)
@@ -628,10 +740,6 @@ public abstract class AbstractOidcClientAuthenticationFlowTest extends AbstractO
                 .build();
     }
 
-    protected ClientSecretJWT buildSecretJwtAuth(String secret) throws JOSEException, URISyntaxException {
-        return buildSecretJwtAuth(clientId, secret);
-    }
-
     protected ClientSecretJWT buildSecretJwtAuth(final String id, String secret) throws JOSEException, URISyntaxException {
         return buildSecretJwtAuth(id, secret, jwtAud);
     }
@@ -642,7 +750,7 @@ public abstract class AbstractOidcClientAuthenticationFlowTest extends AbstractO
                 JWSAlgorithm.HS256, new Secret(secret));
     }
 
-    protected PrivateKeyJWT buildPrivateKeyJwtAuth() throws JOSEException, URISyntaxException {
+    protected PrivateKeyJWT buildPrivateKeyJwtAuth(final String clientId) throws JOSEException, URISyntaxException {
         return new PrivateKeyJWT(new ClientID(clientId), new URI(jwtAud),
                 JWSAlgorithm.RS256, (PrivateKey) rsaPrivateKey, null, null);   
     }
@@ -690,6 +798,7 @@ public abstract class AbstractOidcClientAuthenticationFlowTest extends AbstractO
      * Verify that the given result is a success response.
      *
      * @param result The flow execution result to be verified.
+     * @param clientId The client ID to be used in verification.
      */
-    protected abstract void assertSuccessResponse(final FlowExecutionResult result);
+    protected abstract void assertSuccessResponse(final FlowExecutionResult result, final String clientId);
 }
diff --git a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/ClientCredentialsTokenFlowTest.java b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/ClientCredentialsTokenFlowTest.java
index 3e39f5d5..7643bb69 100644
--- a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/ClientCredentialsTokenFlowTest.java
+++ b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/ClientCredentialsTokenFlowTest.java
@@ -94,6 +94,7 @@ public class ClientCredentialsTokenFlowTest extends AbstractOidcClientAuthentica
     @AfterMethod
     public void tearDown() throws IOException {
         removeMetadata(storageService, clientId);
+        removeMetadata(storageService, clientIdNotMDDriven);
         removeMetadata(storageService, resource);
     }
 
@@ -249,21 +250,25 @@ public class ClientCredentialsTokenFlowTest extends AbstractOidcClientAuthentica
 
     @Test
     public void testInvalidSecretJWTAuthn() throws Exception {
-        final ClientSecretJWT clientAuth = buildSecretJwtAuth(clientSecret + "invalid");
-        final FlowExecutionResult result = launchWithJwtAuthentication(clientAuth, JWSAlgorithm.HS256);
-        assertErrorCode(result, OAuth2Error.INVALID_CLIENT_CODE);
+        for (final String id : clientIds) {
+            final ClientSecretJWT clientAuth = buildSecretJwtAuth(id, clientSecret + "invalid");
+            final FlowExecutionResult result = launchWithJwtAuthentication(clientAuth, JWSAlgorithm.HS256);
+            assertErrorCode(result, OAuth2Error.INVALID_CLIENT_CODE);
+        }
     }
 
     @Test
     public void testValidSecretJWTAuthn() throws Exception {
-        final ClientSecretJWT clientAuth = buildSecretJwtAuth(clientSecret);
-        final FlowExecutionResult result = launchWithJwtAuthentication(clientAuth, JWSAlgorithm.HS256);
-        final AccessTokenResponse response = parseSuccessResponse(result, AccessTokenResponse.class);
-        Assert.assertNotNull(response.getTokens().getBearerAccessToken());
-        Assert.assertEquals(response.getTokens().getBearerAccessToken().getLifetime(), 600);
-        Assert.assertEquals(response.getTokens().getBearerAccessToken().getScope(), scope);
-        verifyClaims(null, response.getTokens().getBearerAccessToken(), clientId, scope,
-                Collections.singletonList(resource), "email", "eduPersonScopedAffiliation");
+        for (final String id : clientIds) {
+            final ClientSecretJWT clientAuth = buildSecretJwtAuth(id, clientSecret);
+            final FlowExecutionResult result = launchWithJwtAuthentication(clientAuth, JWSAlgorithm.HS256);
+            final AccessTokenResponse response = parseSuccessResponse(result, AccessTokenResponse.class);
+            Assert.assertNotNull(response.getTokens().getBearerAccessToken());
+            Assert.assertEquals(response.getTokens().getBearerAccessToken().getLifetime(), 600);
+            Assert.assertEquals(response.getTokens().getBearerAccessToken().getScope(), scope);
+            verifyClaims(null, response.getTokens().getBearerAccessToken(), id, scope,
+                    Collections.singletonList(resource), "email", "eduPersonScopedAffiliation");
+        }
     }
     
     @Test
@@ -292,6 +297,7 @@ public class ClientCredentialsTokenFlowTest extends AbstractOidcClientAuthentica
     
     protected FlowExecutionResult launchWithJwtAuthentication(final JWTAuthentication authnMethod,
             final JWSAlgorithm algorithm) throws Exception {
+        final String clientId = authnMethod.getClientID().getValue();
         storeMetadata(storageService, clientId, clientSecret, scope, JWSAlgorithm.HS256,
                 ClientAuthenticationMethod.CLIENT_SECRET_JWT);
         final Map<String, String> requestParameters = createRequestParameters(clientId, scope, resource);
@@ -302,6 +308,9 @@ public class ClientCredentialsTokenFlowTest extends AbstractOidcClientAuthentica
 
     protected FlowExecutionResult launchWithJwtAuthentication(final JWT jwt, final JWSAlgorithm algorithm,
             final ClientAuthenticationMethod method, final PublicKey publicKey) throws Exception {
+        // use 'iss' claim from JWT as clientId if set, 'sub' otherwise
+        final String iss =  jwt.getJWTClaimsSet().getStringClaim("iss");
+        final String clientId = iss == null ? jwt.getJWTClaimsSet().getStringClaim("sub") : iss;
         if (ClientAuthenticationMethod.CLIENT_SECRET_JWT.equals(method)) {
             storeMetadata(storageService, clientId, clientSecret, scope, algorithm, method);
         } else {
@@ -406,7 +415,7 @@ public class ClientCredentialsTokenFlowTest extends AbstractOidcClientAuthentica
        }
    }
 
-   protected void assertSuccessResponse(final FlowExecutionResult result) {
+   protected void assertSuccessResponse(final FlowExecutionResult result, final String clientId) {
        final AccessTokenResponse response = parseSuccessResponse(result, AccessTokenResponse.class);
        Assert.assertNotNull(response.getTokens().getBearerAccessToken());
        Assert.assertEquals(response.getTokens().getBearerAccessToken().getLifetime(), 600);
diff --git a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/IntrospectionFlowTest.java b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/IntrospectionFlowTest.java
index dafab8ca..f623f88d 100644
--- a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/IntrospectionFlowTest.java
+++ b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/IntrospectionFlowTest.java
@@ -84,6 +84,7 @@ public class IntrospectionFlowTest extends AbstractOidcClientAuthenticationFlowT
     @AfterMethod
     public void tearDown() throws IOException {
         removeMetadata(storageService, clientId);
+        removeMetadata(storageService, clientIdNotMDDriven);
     }
 
     @Test
@@ -453,6 +454,9 @@ public class IntrospectionFlowTest extends AbstractOidcClientAuthenticationFlowT
     
     protected FlowExecutionResult launchWithJwtAuthentication(final JWT jwt, final JWSAlgorithm algorithm,
             final ClientAuthenticationMethod method, final PublicKey publicKey) throws Exception {
+        // use 'iss' claim from JWT as clientId if set, 'sub' otherwise
+        final String iss =  jwt.getJWTClaimsSet().getStringClaim("iss");
+        final String clientId = iss == null ? jwt.getJWTClaimsSet().getStringClaim("sub") : iss;
         if (publicKey == null) {
             storeMetadata(storageService, clientId, clientSecret, scope, algorithm, method);
         } else {
@@ -477,7 +481,7 @@ public class IntrospectionFlowTest extends AbstractOidcClientAuthenticationFlowT
         return new Pair<>("invalid_client", "Client authentication failed");
     }
 
-    protected void assertSuccessResponse(final FlowExecutionResult result) {
+    protected void assertSuccessResponse(final FlowExecutionResult result, final String clientId) {
         final TokenIntrospectionSuccessResponse resp =
                 parseSuccessResponse(result, TokenIntrospectionSuccessResponse.class);
         Assert.assertNotNull(resp);
diff --git a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/RevocationFlowTest.java b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/RevocationFlowTest.java
index 6dd6f8e1..005b45d8 100644
--- a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/RevocationFlowTest.java
+++ b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/RevocationFlowTest.java
@@ -85,6 +85,7 @@ public class RevocationFlowTest extends AbstractOidcClientAuthenticationFlowTest
     @AfterMethod
     public void tearDown() throws IOException {
         removeMetadata(storageService, clientId);
+        removeMetadata(storageService, clientIdNotMDDriven);
         removeMetadata(storageService, clientIdSingle);
     }
 
@@ -213,6 +214,9 @@ public class RevocationFlowTest extends AbstractOidcClientAuthenticationFlowTest
 
     protected FlowExecutionResult launchWithJwtAuthentication(final JWT jwt, final JWSAlgorithm algorithm,
             final ClientAuthenticationMethod method, final PublicKey publicKey) throws Exception {
+        // use 'iss' claim from JWT as clientId if set, 'sub' otherwise
+        final String iss =  jwt.getJWTClaimsSet().getStringClaim("iss");
+        final String clientId = iss == null ? jwt.getJWTClaimsSet().getStringClaim("sub") : iss;
         if (publicKey == null) {
             storeMetadata(storageService, clientId, clientSecret, scope, algorithm, method);
         } else {
@@ -315,7 +319,7 @@ public class RevocationFlowTest extends AbstractOidcClientAuthenticationFlowTest
         parseSuccessResponse(result, OAuth2RevocationSuccessResponse.class);
     }
 
-    protected void assertSuccessResponse(final FlowExecutionResult result) {
+    protected void assertSuccessResponse(final FlowExecutionResult result, final String clientId) {
         Assert.assertNotNull(parseSuccessResponse(result, OAuth2RevocationSuccessResponse.class));
     }
 }
\ No newline at end of file
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 d8ed1599..db9fc492 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
@@ -109,10 +109,11 @@ public class TokenFlowTest extends AbstractOidcClientAuthenticationFlowTest {
     public TokenFlowTest() {
         super(FLOW_ID);
     }
-    
+
     @AfterMethod
     public void removeMetadata() throws IOException {
         removeMetadata(storageService, clientId);
+        removeMetadata(storageService, clientIdNotMDDriven);
         removeMetadata(storageService, clientIdPkcePlain);
         removeMetadata(storageService, clientIdPkceS256);
         removeMetadata(storageService, clientIdCustomTokens);
@@ -634,7 +635,7 @@ public class TokenFlowTest extends AbstractOidcClientAuthenticationFlowTest {
 
     @Test
     public void testValidSecretJWT() throws Exception {
-        final ClientSecretJWT clientAuth = buildSecretJwtAuth(clientSecret);
+        final ClientSecretJWT clientAuth = buildSecretJwtAuth(clientId, clientSecret);
         final FlowExecutionResult result = launchWithJwtAuthentication(clientAuth, JWSAlgorithm.HS256);
         final OIDCTokenResponse response = parseSuccessResponse(result, OIDCTokenResponse.class);
         Assert.assertNotNull(response.getTokens().getAccessToken());
@@ -644,7 +645,7 @@ public class TokenFlowTest extends AbstractOidcClientAuthenticationFlowTest {
 
     @Test
     public void testValidSecretJWTNoAlg() throws Exception {
-        final ClientSecretJWT clientAuth = buildSecretJwtAuth(clientSecret);
+        final ClientSecretJWT clientAuth = buildSecretJwtAuth(clientId, clientSecret);
         final FlowExecutionResult result = launchWithJwtAuthentication(clientAuth, null);
         final OIDCTokenResponse response = parseSuccessResponse(result, OIDCTokenResponse.class);
         Assert.assertNotNull(response.getTokens().getAccessToken());
@@ -785,7 +786,7 @@ public class TokenFlowTest extends AbstractOidcClientAuthenticationFlowTest {
 
     @Test
     public void testInvalidSecretJWT() throws Exception {
-        final ClientSecretJWT clientAuth = buildSecretJwtAuth(clientSecret + "invalid");
+        final ClientSecretJWT clientAuth = buildSecretJwtAuth(clientId, clientSecret + "invalid");
         final FlowExecutionResult result = launchWithJwtAuthentication(clientAuth, JWSAlgorithm.HS256);
         assertErrorCode(result, OAuth2Error.INVALID_CLIENT_CODE);
     }
@@ -1085,6 +1086,7 @@ public class TokenFlowTest extends AbstractOidcClientAuthenticationFlowTest {
     protected FlowExecutionResult launchWithJwtAuthentication(final JWTAuthentication authnMethod, final JWSAlgorithm algorithm,
             final String requestedScope)
             throws Exception {
+        final String clientId = authnMethod.getClientID().getValue();
         final String code = buildAuthorizationCode(clientId, "https://op.example.org", "jdoe", "mock",
                 redirectUri, scope.toString(), null).toString();
         storeMetadata(storageService, clientId, clientSecret, scope, JWSAlgorithm.HS256,
@@ -1133,6 +1135,9 @@ public class TokenFlowTest extends AbstractOidcClientAuthenticationFlowTest {
 
     protected FlowExecutionResult launchWithJwtAuthentication(final JWT jwt, final JWSAlgorithm algorithm,
             final ClientAuthenticationMethod method, final PublicKey publicKey) throws Exception {
+        // use 'iss' claim from JWT as clientId if set, 'sub' otherwise
+        final String iss =  jwt.getJWTClaimsSet().getStringClaim("iss");
+        final String clientId = iss == null ? jwt.getJWTClaimsSet().getStringClaim("sub") : iss;
         final String code = buildAuthorizationCode(clientId, "https://op.example.org", "jdoe", "mock",
                 redirectUri, scope.toString(), null).toString();
         if (publicKey == null) {
@@ -1181,7 +1186,7 @@ public class TokenFlowTest extends AbstractOidcClientAuthenticationFlowTest {
         return new Pair<>("invalid_client", "Client authentication failed");
     }
 
-    protected void assertSuccessResponse(final FlowExecutionResult result) {
+    protected void assertSuccessResponse(final FlowExecutionResult result, final String clientId) {
         final OIDCTokenResponse response = parseSuccessResponse(result, OIDCTokenResponse.class);
         Assert.assertNotNull(response);
         Assert.assertNotNull(response.getTokens().getAccessToken());
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 97170199..6bda558c 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
@@ -71,6 +71,17 @@
     </bean>
 
     <util:list id="shibboleth.RelyingPartyOverrides">
+        <bean parent="RelyingPartyByName" c:relyingPartyIds="mockClientIdNotMDDriven">
+            <property name="profileConfigurations">
+                 <list>
+                     <ref bean="OIDC.SSO" />
+                     <ref bean="OAUTH2.Token" />
+                     <ref bean="OIDC.UserInfo" />
+                     <ref bean="OAUTH2.Introspection" />
+                     <ref bean="OAUTH2.Revocation" />
+                 </list>
+            </property>
+        </bean>
         <bean parent="RelyingPartyByName" c:relyingPartyIds="mockClientIdEncryptionEnforced">
             <property name="profileConfigurations">
                  <list>

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list