[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