[java-idp-plugin-oidc-rp] branch main updated: JOIDCRP-74 & JOIDCRP-75 - Improve audience handling in JWT client authentication

Phil Smart philip.smart at jisc.ac.uk
Wed Jun 4 14:23:18 UTC 2025


This is an automated email from the git hooks/post-receive script.

philsmart pushed a commit to branch main
in repository java-idp-plugin-oidc-rp.

View the commit online:
http://git.shibboleth.net/view/?p=java-idp-plugin-oidc-rp.git;a=commit;h=f2d2e04d51659ec8f6f53e783e4dc3c1e96df808

The following commit(s) were added to refs/heads/main by this push:
     new f2d2e04  JOIDCRP-74 & JOIDCRP-75 - Improve audience handling in JWT client authentication
f2d2e04 is described below

commit f2d2e04d51659ec8f6f53e783e4dc3c1e96df808
Author: Phil Smart <philip.smart at jisc.ac.uk>
AuthorDate: Wed Jun 4 15:23:16 2025 +0100

    JOIDCRP-74 & JOIDCRP-75 - Improve audience handling in JWT client
    authentication
    
     - take audience flag override from the profile configuration, see
    https://shibboleth.atlassian.net/browse/JOIDCRP-74.
     - add JWT typ header override from the profile configuration, see
    https://shibboleth.atlassian.net/browse/JOIDCRP-75.
---
 ...izeOAuth2ClientAuthenticationMethodHandler.java | 52 +++++-----------------
 .../oidc-relying-party-authn-beans.xml             |  3 +-
 ...Auth2ClientAuthenticationMethodHandlerTest.java |  4 +-
 pom.xml                                            |  4 +-
 4 files changed, 15 insertions(+), 48 deletions(-)

diff --git a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/InitializeOAuth2ClientAuthenticationMethodHandler.java b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/InitializeOAuth2ClientAuthenticationMethodHandler.java
index 703c8e8..fb29d54 100644
--- a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/InitializeOAuth2ClientAuthenticationMethodHandler.java
+++ b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/InitializeOAuth2ClientAuthenticationMethodHandler.java
@@ -18,7 +18,6 @@ import java.time.Duration;
 import java.time.Instant;
 import java.util.Date;
 import java.util.function.Function;
-import java.util.function.Predicate;
 
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
@@ -33,7 +32,6 @@ import org.opensaml.profile.context.navigate.ParentProfileRequestContextLookup;
 import org.slf4j.Logger;
 
 import com.nimbusds.jose.Algorithm;
-import com.nimbusds.jose.JOSEObjectType;
 import com.nimbusds.jose.JWSAlgorithm;
 import com.nimbusds.jwt.JWTClaimsSet;
 import com.nimbusds.jwt.SignedJWT;
@@ -60,7 +58,6 @@ import net.shibboleth.oidc.security.jose.context.SecurityParametersContext;
 import net.shibboleth.profile.context.RelyingPartyContext;
 import net.shibboleth.shared.annotation.constraint.NonnullBeforeExec;
 import net.shibboleth.shared.logic.Constraint;
-import net.shibboleth.shared.logic.PredicateSupport;
 import net.shibboleth.shared.primitive.LoggerFactory;
 import net.shibboleth.shared.primitive.StringSupport;
 
@@ -136,14 +133,7 @@ public class InitializeOAuth2ClientAuthenticationMethodHandler extends AbstractM
     
     /** The stashed peer entity context.*/
     @Nullable private OIDCPeerEntityContext peerEntityContext;
-    
-    /** 
-     * Should the audience claim of a JWT client assertion (if used) be the token endpoint? Defaults to false: 
-     * the audience will be the issuer identifier of the OP.
-     */
-    @Nonnull private Predicate<ProfileRequestContext> tokenEndpointAsAudience;
-
-    
+        
     /** Constructor.*/
     public InitializeOAuth2ClientAuthenticationMethodHandler() {
         // Default under the OIDC Peer Entity Context, create is true
@@ -155,7 +145,6 @@ public class InitializeOAuth2ClientAuthenticationMethodHandler extends AbstractM
         providerMetadataLookupStrategy = new ChildContextLookup<>(OIDCProviderMetadataContext.class).compose(
                 new ChildContextLookup<>(OIDCPeerEntityContext.class));
         jwtBearerExpiryOffset = Duration.ofSeconds(30);
-        tokenEndpointAsAudience = PredicateSupport.alwaysFalse();
         oidcPeerEntityContextLookupStrategy = new ChildContextLookup<>(OIDCPeerEntityContext.class);
     }
     
@@ -236,34 +225,7 @@ public class InitializeOAuth2ClientAuthenticationMethodHandler extends AbstractM
 
         oauth2ClientAuthenticationContextLookupStrategy = Constraint.isNotNull(strgy, 
                 "OAuth2 client authentication context lookup strategy cannot be null");
-    }
-    
-    /**
-     * Set a condition that determines if the client assertion JWT audience claim should be based on the token 
-     * endpoint URL? if false, the issuer identifier of the OP will be used (recommended).
-     * 
-     * @param condition the condition to evaluate
-     * 
-     * @since 2.3.0
-     */
-    public void setTokenEndpointAsAudience(final Predicate<ProfileRequestContext> condition) {
-        checkSetterPreconditions();
-        tokenEndpointAsAudience = Constraint.isNotNull(condition, "AudienceAsTokenEndpoint can not be null");
-    }
-    
-    /**
-     * Should the client assertion JWT audience claim be based on the token endpoint URL? if false, the issuer 
-     * identifier of the OP will be used (recommended).
-     * 
-     * @param flag the flag to set
-     * 
-     * @since 2.3.0
-     */
-    public void setTokenEndpointAsAudience(final boolean flag) {
-        checkSetterPreconditions();
-        tokenEndpointAsAudience = flag ? PredicateSupport.alwaysTrue() : PredicateSupport.alwaysFalse();
-    }
-    
+    }    
     
     /** {@inheritDoc} */
     @Override
@@ -443,7 +405,7 @@ public class InitializeOAuth2ClientAuthenticationMethodHandler extends AbstractM
             throws MessageHandlerException{
         
         String audience;
-        if (tokenEndpointAsAudience.test(PRC_LOOKUP.apply(messageContext))) {
+        if (profileConfiguration.isUseTargetedEndpointAsJWTAudience(PRC_LOOKUP.apply(messageContext))) {
             audience = providerMetadata.getTokenEndpointURI().toString();
         } else {
             final var localPeerEntityCtx = peerEntityContext;
@@ -495,9 +457,15 @@ public class InitializeOAuth2ClientAuthenticationMethodHandler extends AbstractM
         }
         final JWTClaimsSet claims = buildClientAuthenticationJwtClaims(messageContext);
         
+        String jwtType = profileConfiguration.getClientAuthenticationJWTType(PRC_LOOKUP.apply(messageContext));
+        if (jwtType == null) {
+            //default to 'client-authentication+jwt' see RFC 7523
+            jwtType = "client-authentication+jwt";
+        }
+        
         try {
             final JWSTokenSigner signer = new JWSTokenSigner(signingParams);
-            final SignedJWT signed = signer.sign(claims, JOSEObjectType.JWT.getType());    
+            final SignedJWT signed = signer.sign(claims, jwtType);    
             if (log.isDebugEnabled() && !log.isTraceEnabled()) {
                 log.debug("{} Signed JWT Bearer Token for client authentication'", getLogPrefix());
             } else if (log.isTraceEnabled()) {
diff --git a/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OIDCRelyingParty/oidc-relying-party-authn-beans.xml b/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OIDCRelyingParty/oidc-relying-party-authn-beans.xml
index ae77c9b..f9c56bf 100644
--- a/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OIDCRelyingParty/oidc-relying-party-authn-beans.xml
+++ b/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OIDCRelyingParty/oidc-relying-party-authn-beans.xml
@@ -404,8 +404,7 @@
                          <bean id="InitializeOAuth2ClientAuthenticationMethodHandler" scope="prototype"
                             class="net.shibboleth.idp.plugin.authn.oidc.rp.impl.InitializeOAuth2ClientAuthenticationMethodHandler"
                             p:securityParametersContextLookupStrategy-ref="shibboleth.ChildLookupOrCreate.SecurityParametersFromOAuth2ClientAuthenticationContext"
-                            p:jwtBearerExpiryOffset="%{idp.authn.oidc.rp.client.authenticationMethod.jwt.expiryOffset:PT30S}"
-                            p:tokenEndpointAsAudience="%{idp.authn.oidc.rp.client.authenticationMethod.tokenEndpointAsAudience:false}"/>
+                            p:jwtBearerExpiryOffset="%{idp.authn.oidc.rp.client.authenticationMethod.jwt.expiryOffset:PT30S}"/>
                     </list>
                 </property>            
             </bean>
diff --git a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/InitializeOAuth2ClientAuthenticationMethodHandlerTest.java b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/InitializeOAuth2ClientAuthenticationMethodHandlerTest.java
index f000c4c..7102f09 100644
--- a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/InitializeOAuth2ClientAuthenticationMethodHandlerTest.java
+++ b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/InitializeOAuth2ClientAuthenticationMethodHandlerTest.java
@@ -167,7 +167,7 @@ public class InitializeOAuth2ClientAuthenticationMethodHandlerTest extends Abstr
         final var peerEntityCtx = outboundMsgCtx.getSubcontext(OIDCPeerEntityContext.class);        
         assert peerEntityCtx != null;
         peerEntityCtx.setIdentifier("https://op.example.com");
-        handler.setTokenEndpointAsAudience(true);
+        partyConfig.setUseTargetedEndpointAsJWTAudience(true);
         
         outboundMsgCtx.addSubcontext(secContext);
         
@@ -295,7 +295,7 @@ public class InitializeOAuth2ClientAuthenticationMethodHandlerTest extends Abstr
         final var peerEntityCtx = outboundMsgCtx.getSubcontext(OIDCPeerEntityContext.class);
         assert peerEntityCtx != null;
         peerEntityCtx.setIdentifier("https://op.example.com");
-        handler.setTokenEndpointAsAudience(true);
+        partyConfig.setUseTargetedEndpointAsJWTAudience(true);
         
         handler.initialize();
         handler.invoke(outboundMsgCtx);
diff --git a/pom.xml b/pom.xml
index f7ec1d2..c66a542 100644
--- a/pom.xml
+++ b/pom.xml
@@ -26,9 +26,9 @@
         <shib-shared.testing.version>9.0.0</shib-shared.testing.version>
         <okhttp3.tls.version>4.9.3</okhttp3.tls.version>        
         <oidc-config.groupId>net.shibboleth.idp.plugin.config.oidc</oidc-config.groupId>
-        <oidc-config.version>2.1.0</oidc-config.version>
+        <oidc-config.version>2.2.1-SNAPSHOT</oidc-config.version>
         <oidc-common.groupId>net.shibboleth.oidc</oidc-common.groupId>
-        <oidc-common.version>3.1.0</oidc-common.version>
+        <oidc-common.version>3.3.0-SNAPSHOT</oidc-common.version>
         <shib-shared.groupId>net.shibboleth</shib-shared.groupId>
         <shib-shared.version>9.0.0</shib-shared.version>
         <shib-profile.groupId>net.shibboleth</shib-profile.groupId>

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


More information about the commits mailing list