[java-idp-oidc] branch main updated: JOIDC-244 - Support client authentication JWT header type validation

Henri Mikkonen henri.mikkonen at iki.fi
Mon Jun 9 15:28:16 UTC 2025


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=219ae1e5a7c94d1943fadd47648f58bd64fabcdf

The following commit(s) were added to refs/heads/main by this push:
     new 219ae1e5 JOIDC-244 - Support client authentication JWT header type validation
219ae1e5 is described below

commit 219ae1e5a7c94d1943fadd47648f58bd64fabcdf
Author: Henri Mikkonen <henri.mikkonen at iki.fi>
AuthorDate: Mon Jun 9 18:27:52 2025 +0300

    JOIDC-244 - Support client authentication JWT header type validation
    
    https://shibboleth.atlassian.net/browse/JOIDC-244
    
    - Add requiredJwtTypeHeaderLookupStrategy to JWTCredentialValidator
      - Defaults to fetching the value from profile configuration (which defaults to null)
    - Any non-null value is considered as mandatory to be matched
---
 .../oidc/op/authn/impl/JWTCredentialValidator.java | 36 ++++++++-
 .../op/authn/impl/JWTCredentialValidatorTest.java  | 90 +++++++++++++++++++++-
 .../AbstractOidcClientAuthenticationFlowTest.java  | 33 ++++++++
 .../oidc/op/profile/flow/AbstractOidcFlowTest.java | 12 ++-
 .../op/profile/flow/IntrospectionFlowTest.java     |  1 +
 .../op/profile/flow/PushedAuthorizeFlowTest.java   |  1 +
 .../oidc/op/profile/flow/RevocationFlowTest.java   |  1 +
 .../plugin/oidc/op/profile/flow/TokenFlowTest.java |  1 +
 .../shibboleth/idp/module/conf/relying-party.xml   | 11 +++
 9 files changed, 180 insertions(+), 6 deletions(-)

diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/JWTCredentialValidator.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/JWTCredentialValidator.java
index 4f1c8fac..67b545b5 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/JWTCredentialValidator.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/JWTCredentialValidator.java
@@ -15,6 +15,7 @@
 package net.shibboleth.idp.plugin.oidc.op.authn.impl;
 
 import java.text.ParseException;
+import java.util.Optional;
 import java.util.function.Function;
 
 import javax.annotation.Nonnull;
@@ -30,11 +31,13 @@ import net.shibboleth.oidc.authn.context.OAuth2ClientAuthenticationContext;
 import net.shibboleth.oidc.jwt.claims.ClaimsValidator;
 import net.shibboleth.oidc.jwt.claims.JWTValidationException;
 import net.shibboleth.oidc.profile.config.navigate.ClaimsValidatorLookupFunction;
+import net.shibboleth.oidc.profile.config.navigate.ClientAuthenticationJWTTypeLookupFunction;
 import net.shibboleth.oidc.security.jose.context.SecurityParametersContext;
 import net.shibboleth.shared.annotation.constraint.NotEmpty;
 import net.shibboleth.shared.annotation.constraint.ThreadSafeAfterInit;
 import net.shibboleth.shared.logic.Constraint;
 import net.shibboleth.shared.primitive.LoggerFactory;
+import net.shibboleth.shared.primitive.StringSupport;
 
 import org.opensaml.messaging.context.navigate.ChildContextLookup;
 import org.opensaml.profile.context.ProfileRequestContext;
@@ -69,7 +72,10 @@ public class JWTCredentialValidator extends AbstractCredentialValidator {
 
     /** Strategy used to obtain {@link ClaimsValidator}. */
     @Nonnull private Function<ProfileRequestContext,ClaimsValidator> claimsValidatorLookupStrategy;
-    
+
+    /** Strategy used to fetch required JWT type header value. */
+    @Nonnull private Function<ProfileRequestContext,String> requiredJwtTypeHeaderLookupStrategy;
+
     /** Whether to save the JWT in the Java Subject's public credentials. */
     private boolean saveTokenToCredentialSet;
     
@@ -89,6 +95,7 @@ public class JWTCredentialValidator extends AbstractCredentialValidator {
         securityParametersLookupStrategy = spls;
         
         claimsValidatorLookupStrategy = new ClaimsValidatorLookupFunction();
+        requiredJwtTypeHeaderLookupStrategy = new ClientAuthenticationJWTTypeLookupFunction();
     }
     
     /**
@@ -142,6 +149,20 @@ public class JWTCredentialValidator extends AbstractCredentialValidator {
         
         saveTokenToCredentialSet = flag;
     }
+
+    /**
+     * Set the strategy used to fetch required JWT type header value.
+     *
+     * @param strategy lookup strategy
+     *
+     * @since 4.3.0
+     */
+    public void setRequiredJwtTypeHeaderLookupStrategy(@Nonnull final Function<ProfileRequestContext,String> strategy) {
+        checkSetterPreconditions();
+
+        requiredJwtTypeHeaderLookupStrategy =
+                Constraint.isNotNull(strategy, "RequiredJwtTypeHeaderLookupStrategy cannot be null");
+    }
     
 // Checkstyle: CyclomaticComplexity OFF
     /** {@inheritDoc} */
@@ -218,6 +239,19 @@ public class JWTCredentialValidator extends AbstractCredentialValidator {
             @Nonnull final SignedJWT jwt, @Nonnull final ClientID clientId)
                     throws ParseException, JWTValidationException {
 
+        final String requiredType = requiredJwtTypeHeaderLookupStrategy.apply(profileRequestContext);
+        if (StringSupport.trimOrNull(requiredType) != null) {
+            log.debug("{} Type header is required to be {}", getLogPrefix(), requiredType);
+            final String type = Optional.ofNullable(jwt.getHeader().getType())
+                    .map(joseType -> joseType.getType())
+                    .orElse(null);
+            if (!requiredType.equals(type)) {
+                log.warn("{} JWT validation failed for client '{}': Invalid JWT type header {}",
+                        getLogPrefix(), clientId, type);
+                throw new JWTValidationException("Invalid JWT type header " + type);
+            }
+        }
+
         final ClaimsValidator validator = claimsValidatorLookupStrategy.apply(profileRequestContext);
         if (validator == null) {
             log.warn("{} JWT validation failed for client '{}': No ClaimsValidator found in configuration",
diff --git a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/JWTCredentialValidatorTest.java b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/JWTCredentialValidatorTest.java
index 8ca18723..27d72da2 100644
--- a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/JWTCredentialValidatorTest.java
+++ b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/JWTCredentialValidatorTest.java
@@ -25,8 +25,11 @@ import java.time.Instant;
 import java.util.Collections;
 import java.util.Date;
 import java.util.List;
+import java.util.function.Function;
 
+import org.mockito.Mockito;
 import org.opensaml.messaging.context.navigate.ChildContextLookup;
+import org.opensaml.profile.context.ProfileRequestContext;
 import org.opensaml.storage.ReplayCache;
 import org.opensaml.storage.impl.MemoryStorageService;
 import org.opensaml.storage.impl.StorageServiceReplayCache;
@@ -37,6 +40,7 @@ import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
 import com.nimbusds.jose.JOSEException;
+import com.nimbusds.jose.JOSEObjectType;
 import com.nimbusds.jose.JWSAlgorithm;
 import com.nimbusds.jose.JWSHeader;
 import com.nimbusds.jose.crypto.MACSigner;
@@ -97,7 +101,10 @@ public class JWTCredentialValidatorTest extends BaseAuthenticationContextTest {
     private ClaimsValidator claimsValidator;
     private JWTCredentialValidator validator;
     private ValidateCredentials action;
-    
+
+    @SuppressWarnings("unchecked")
+    private Function<ProfileRequestContext, String> typeHeaderLookup = Mockito.mock(Function.class);
+
     @BeforeClass
     public void initKeys() throws NoSuchAlgorithmException {
         final KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
@@ -135,6 +142,7 @@ public class JWTCredentialValidatorTest extends BaseAuthenticationContextTest {
         validator = new JWTCredentialValidator();
         validator.setId("test");
         validator.setSecurityParametersLookupStrategy(new ChildContextLookup<>(SecurityParametersContext.class));
+        validator.setRequiredJwtTypeHeaderLookupStrategy(typeHeaderLookup);
         validator.initialize();
         
         action = new ValidateCredentials();
@@ -262,19 +270,38 @@ public class JWTCredentialValidatorTest extends BaseAuthenticationContextTest {
 
     protected SignedJWT createSecretJWT(final JWTClaimsSet claimsSet, final String clientSecret)
             throws JOSEException {
-        final SignedJWT jwt = new SignedJWT(new JWSHeader(JWSAlgorithm.HS256), claimsSet);
+        return createSecretJWT(claimsSet, clientSecret, null);
+    }
+
+    protected SignedJWT createSecretJWT(final JWTClaimsSet claimsSet, final String clientSecret,
+            final String typeHeader) throws JOSEException {
+        final SignedJWT jwt;
+        if (typeHeader == null) {
+            jwt = new SignedJWT(new JWSHeader(JWSAlgorithm.HS256), claimsSet);
+        } else {
+            jwt = new SignedJWT(new JWSHeader.Builder(JWSAlgorithm.HS256)
+                    .type(new JOSEObjectType(typeHeader)).build(), claimsSet);
+        }
         final MACSigner signer = new MACSigner(clientSecret);
         jwt.sign(signer);
         return jwt;
     }
-    
+
     protected SignedJWT createPrivateKeyJWT(final JWTClaimsSet claimsSet) throws JOSEException {
         final SignedJWT jwt = new SignedJWT(new JWSHeader(JWSAlgorithm.RS256), claimsSet);
         final RSASSASigner signer = new RSASSASigner(rsaPrivateKey);
         jwt.sign(signer);
         return jwt;
     }
-    
+
+    protected SignedJWT createPrivateKeyJWT(final JWTClaimsSet claimsSet, final String header) throws JOSEException {
+        final SignedJWT jwt = new SignedJWT(new JWSHeader.Builder(JWSAlgorithm.RS256)
+                .type(new JOSEObjectType(header)).build(), claimsSet);
+        final RSASSASigner signer = new RSASSASigner(rsaPrivateKey);
+        jwt.sign(signer);
+        return jwt;
+    }
+
     @Test
     public void testNoClaimsValidator() throws Exception {
         ((AbstractOAuth2ClientAuthenticableProfileConfiguration) prc.ensureSubcontext(
@@ -287,6 +314,25 @@ public class JWTCredentialValidatorTest extends BaseAuthenticationContextTest {
     public void testSecretJwt() throws JOSEException, NoSuchAlgorithmException {
         initializeTokenRequest(ClientAuthenticationMethod.CLIENT_SECRET_JWT, createSecretJWT(validClaimsSet()), true);
 
+        Mockito.when(typeHeaderLookup.apply(Mockito.any())).thenReturn(null);
+        final Event event = action.execute(src);
+        ActionTestingSupport.assertProceedEvent(event);
+        
+        final AuthenticationContext ac = prc.ensureSubcontext(AuthenticationContext.class);
+        final AuthenticationResult ar = ac.getAuthenticationResult();
+        Assert.assertNotNull(ar);
+        assert ar != null;
+        Assert.assertEquals(ar.getSubject().getPrincipals(UsernamePrincipal.class).iterator()
+                .next().getName(), clientId.getValue());
+    }
+
+    @Test
+    public void testSecretJwt_enforcedHeader() throws JOSEException, NoSuchAlgorithmException {
+        final String header = "enforcedTypeHeader";
+        initializeTokenRequest(ClientAuthenticationMethod.CLIENT_SECRET_JWT, createSecretJWT(validClaimsSet(),
+                clientSecret.toString(), header), true);
+        Mockito.when(typeHeaderLookup.apply(Mockito.any())).thenReturn(header);
+
         final Event event = action.execute(src);
         ActionTestingSupport.assertProceedEvent(event);
         
@@ -298,10 +344,38 @@ public class JWTCredentialValidatorTest extends BaseAuthenticationContextTest {
                 .next().getName(), clientId.getValue());
     }
 
+
+    @Test
+    public void testSecretJwt_missingMandatoryHeader() throws Exception {
+        final String header = "enforcedTypeHeader";
+        Mockito.when(typeHeaderLookup.apply(Mockito.any())).thenReturn(header);
+        testFailingJwtAuth(ClientAuthenticationMethod.CLIENT_SECRET_JWT,
+                createSecretJWT(validClaimsSet()), false, true);
+    }
+
     @Test
     public void testPrivateKeyJwt() throws JOSEException, NoSuchAlgorithmException {
         initializeTokenRequest(ClientAuthenticationMethod.PRIVATE_KEY_JWT, createPrivateKeyJWT(validClaimsSet()), true);
         
+        Mockito.when(typeHeaderLookup.apply(Mockito.any())).thenReturn(null);
+        final Event event = action.execute(src);
+        ActionTestingSupport.assertProceedEvent(event);
+        
+        final AuthenticationContext ac = prc.ensureSubcontext(AuthenticationContext.class);
+        final AuthenticationResult ar = ac.getAuthenticationResult();
+        Assert.assertNotNull(ar);
+        assert ar != null;
+        Assert.assertEquals(ar.getSubject().getPrincipals(UsernamePrincipal.class).iterator()
+                .next().getName(), clientId.getValue());
+    }
+
+    @Test
+    public void testPrivateKeyJwt_enforcedHeader() throws JOSEException, NoSuchAlgorithmException {
+        final String header = "enforcedTypeHeader";
+        initializeTokenRequest(ClientAuthenticationMethod.PRIVATE_KEY_JWT,
+                createPrivateKeyJWT(validClaimsSet(), header), true);
+        Mockito.when(typeHeaderLookup.apply(Mockito.any())).thenReturn(header);
+        
         final Event event = action.execute(src);
         ActionTestingSupport.assertProceedEvent(event);
         
@@ -313,6 +387,14 @@ public class JWTCredentialValidatorTest extends BaseAuthenticationContextTest {
                 .next().getName(), clientId.getValue());
     }
 
+    @Test
+    public void testPrivateKeyJwt_missingMandatoryHeader() throws Exception {
+        final String header = "enforcedTypeHeader";
+        Mockito.when(typeHeaderLookup.apply(Mockito.any())).thenReturn(header);
+        testFailingJwtAuth(ClientAuthenticationMethod.PRIVATE_KEY_JWT,
+                createPrivateKeyJWT(validClaimsSet()), false, true);
+    }
+
     @Test
     public void testInvalidSecretJwt_iatInTheFuture() throws Exception {
         testFailingJwtAuth(ClientAuthenticationMethod.CLIENT_SECRET_JWT,
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 8eaec760..fe40a174 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
@@ -62,6 +62,7 @@ public abstract class AbstractOidcClientAuthenticationFlowTest extends AbstractO
     String clientSecretSaml = "mockClientSecretmockClientSecretmockClientSecret";
     String clientIdDPoPProofEnforced = "mockClientIdDPoPProofEnforced";
     String clientIdEndpointAudienceDisabled = "mockClientIdEndpointAudienceDisabled";
+    String clientIdRequireClientAuthenticationJWTType = "mockClientIdRequireClientAuthenticationJWTType";
 
     String jwtAud;
     String issuer = "https://op.example.org";
@@ -213,6 +214,38 @@ public abstract class AbstractOidcClientAuthenticationFlowTest extends AbstractO
         }
     }
 
+    @Test
+    public void testValidSecretJWTHS256_IssuerAudience_typeSetNotEnforced() throws Exception {
+        final List<String> ids = new ArrayList<>(clientIds);
+        ids.add(clientIdEndpointAudienceDisabled);
+        for (final String id : ids) {
+            final SignedJWT jwt = createSecretJWT(validClaimsSet(id, issuer), clientSecret, JWSAlgorithm.HS256,
+                    "client-authentication+jwt");
+            final FlowExecutionResult result = launchWithJwtAuthentication(jwt, null,
+                    ClientAuthenticationMethod.CLIENT_SECRET_JWT);
+            assertSuccessResponse(result, id);
+        }
+    }
+
+    @Test
+    public void testValidSecretJWTHS256_IssuerAudience_typeSetAndEnforced() throws Exception {
+        final SignedJWT jwt = createSecretJWT(validClaimsSet(clientIdRequireClientAuthenticationJWTType, issuer),
+                clientSecret, JWSAlgorithm.HS256, "client-authentication+jwt");
+        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, null,
+                ClientAuthenticationMethod.CLIENT_SECRET_JWT);
+        assertSuccessResponse(result, clientIdRequireClientAuthenticationJWTType);
+    }
+
+    @Test
+    public void testValidSecretJWTHS256_IssuerAudience_typeNotSetButEnforced() throws Exception {
+        final SignedJWT jwt = createSecretJWT(validClaimsSet(clientIdRequireClientAuthenticationJWTType, issuer),
+                clientSecret, JWSAlgorithm.HS256);
+        final FlowExecutionResult result = launchWithJwtAuthentication(jwt, null,
+                ClientAuthenticationMethod.CLIENT_SECRET_JWT);
+        assertErrorCode(result, getErrorDetaisForJWTValidation().getFirst());
+        assertErrorDescriptionContains(result, getErrorDetaisForJWTValidation().getSecond());
+    }
+
     @Test
     public void testValidSecretJWTHS256_noRegisteredAlg() throws Exception {
         for (final String id : clientIds) {
diff --git a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/AbstractOidcFlowTest.java b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/AbstractOidcFlowTest.java
index 6d35d051..9177af6f 100644
--- a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/AbstractOidcFlowTest.java
+++ b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/AbstractOidcFlowTest.java
@@ -476,7 +476,17 @@ public abstract class AbstractOidcFlowTest extends AbstractFlowTest {
 
     protected static SignedJWT createSecretJWT(final JWTClaimsSet claimsSet, final String clientSecret,
             final JWSAlgorithm algorithm) {
-        final SignedJWT jwt = new SignedJWT(new JWSHeader(algorithm), claimsSet);
+        return createSecretJWT(claimsSet, clientSecret, algorithm, null);
+    }
+
+    protected static SignedJWT createSecretJWT(final JWTClaimsSet claimsSet, final String clientSecret,
+            final JWSAlgorithm algorithm, final String type) {
+        final SignedJWT jwt;
+        if (type != null) {
+            jwt = new SignedJWT(new JWSHeader.Builder(algorithm).type(new JOSEObjectType(type)).build(), claimsSet);
+        } else {
+            jwt = new SignedJWT(new JWSHeader(algorithm), claimsSet);
+        }
         try {
             final MACSigner signer = new MACSigner(clientSecret);
             jwt.sign(signer);
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 b69cbdd1..98107a7a 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
@@ -91,6 +91,7 @@ public class IntrospectionFlowTest extends AbstractOidcClientAuthenticationFlowT
         removeMetadata(storageService, clientIdNotMDDriven);
         removeMetadata(storageService, clientIdDPoPProofEnforced);
         removeMetadata(storageService, clientIdEndpointAudienceDisabled);
+        removeMetadata(storageService, clientIdRequireClientAuthenticationJWTType);
     }
 
     @Test
diff --git a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/PushedAuthorizeFlowTest.java b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/PushedAuthorizeFlowTest.java
index ebcee2f6..2465e7c7 100644
--- a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/PushedAuthorizeFlowTest.java
+++ b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/PushedAuthorizeFlowTest.java
@@ -106,6 +106,7 @@ public class PushedAuthorizeFlowTest extends AbstractOidcClientAuthenticationFlo
         removeMetadata(storageService, "mockPublicClientIdPKCEPlainUnforced");
         removeMetadata(storageService, "mockClientIdDPoPAccessToken");
         removeMetadata(storageService, clientIdEndpointAudienceDisabled);
+        removeMetadata(storageService, clientIdRequireClientAuthenticationJWTType);
     }
 
     @Test
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 1be0d836..371c51e0 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
@@ -89,6 +89,7 @@ public class RevocationFlowTest extends AbstractOidcClientAuthenticationFlowTest
         removeMetadata(storageService, clientIdSingle);
         removeMetadata(storageService, clientIdDPoPProofEnforced);
         removeMetadata(storageService, clientIdEndpointAudienceDisabled);
+        removeMetadata(storageService, clientIdRequireClientAuthenticationJWTType);
     }
 
     @Test
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 c2b64a1a..18ae8094 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
@@ -140,6 +140,7 @@ public class TokenFlowTest extends AbstractOidcClientAuthenticationFlowTest {
         removeMetadata(storageService, clientIdDPoPJwtBearerAccessToken);
         removeMetadata(storageService, clientIdAlwaysBearerAccessToken);
         removeMetadata(storageService, clientIdEndpointAudienceDisabled);
+        removeMetadata(storageService, clientIdRequireClientAuthenticationJWTType);
     }
 
     @Test
diff --git a/idp-oidc-extension-impl/src/test/resources/net/shibboleth/idp/module/conf/relying-party.xml b/idp-oidc-extension-impl/src/test/resources/net/shibboleth/idp/module/conf/relying-party.xml
index 093937a4..c87a9ab6 100644
--- a/idp-oidc-extension-impl/src/test/resources/net/shibboleth/idp/module/conf/relying-party.xml
+++ b/idp-oidc-extension-impl/src/test/resources/net/shibboleth/idp/module/conf/relying-party.xml
@@ -87,6 +87,17 @@
                  </list>
             </property>
         </bean>
+        <bean parent="RelyingPartyByName" c:relyingPartyIds="mockClientIdRequireClientAuthenticationJWTType">
+            <property name="profileConfigurations">
+                 <list>
+                     <bean parent="OIDC.SSO" p:responseModes="fragment" p:clientAuthenticationJWTType="client-authentication+jwt"/>
+                     <bean parent="OAUTH2.Token.MDDriven" p:clientAuthenticationJWTType="client-authentication+jwt"/>
+                     <bean parent="OAUTH2.Introspection.MDDriven" p:clientAuthenticationJWTType="client-authentication+jwt"/>
+                     <bean parent="OAUTH2.Revocation.MDDriven" p:clientAuthenticationJWTType="client-authentication+jwt"/>
+                     <bean parent="OAUTH2.PAR.MDDriven" p:clientAuthenticationJWTType="client-authentication+jwt"/>
+                 </list>
+            </property>
+        </bean>
         <bean parent="RelyingPartyByName" c:relyingPartyIds="mockClientIdFragmentResponseMode">
             <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