This is an automated email from the ASF dual-hosted git repository. coheigea pushed a commit to branch 4.1.x-fixes in repository https://gitbox.apache.org/repos/asf/cxf.git
commit 5577fc3aa8f88c3c05f83763c76e41b4afbe66cc Author: Guillaume Nodet <[email protected]> AuthorDate: Thu May 7 15:22:41 2026 +0200 RFC 9068: Set typ header to at+jwt for JWT access tokens (#2948) Per RFC 9068 Section 2.1, JWT access tokens MUST include a typ header parameter set to "at+jwt". This change: - Adds TYPE_AT_JWT constant to JoseConstants - Adds AT_JWT member to JoseType enum with proper lookup - Sets the at+jwt type on both JWS and JWE headers when producing JWT access tokens in AbstractOAuthDataProvider Closes #990 Co-authored-by: Claude Opus 4.6 <[email protected]> --- .../java/org/apache/cxf/rs/security/jose/common/JoseConstants.java | 1 + .../main/java/org/apache/cxf/rs/security/jose/common/JoseType.java | 5 ++++- .../cxf/rs/security/oauth2/provider/AbstractOAuthDataProvider.java | 7 ++++++- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/common/JoseConstants.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/common/JoseConstants.java index 092581d3fd0..017f814411d 100644 --- a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/common/JoseConstants.java +++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/common/JoseConstants.java @@ -43,6 +43,7 @@ public final class JoseConstants extends RSSecurityConstants { public static final String JWS_HEADER_B64_STATUS_HEADER = "b64"; public static final String TYPE_JWT = "JWT"; + public static final String TYPE_AT_JWT = "at+jwt"; public static final String TYPE_JOSE = "JOSE"; public static final String TYPE_JOSE_JSON = "JOSE+JSON"; public static final String MEDIA_TYPE_JOSE = "application/jose"; diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/common/JoseType.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/common/JoseType.java index 647fb163fe0..cea5fdf0a8b 100644 --- a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/common/JoseType.java +++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/common/JoseType.java @@ -22,7 +22,8 @@ package org.apache.cxf.rs.security.jose.common; public enum JoseType { JOSE(JoseConstants.TYPE_JOSE), JOSE_JSON(JoseConstants.TYPE_JOSE_JSON), - JWT(JoseConstants.TYPE_JWT); + JWT(JoseConstants.TYPE_JWT), + AT_JWT(JoseConstants.TYPE_AT_JWT); private final String type; JoseType(String type) { @@ -33,6 +34,8 @@ public enum JoseType { return null; } else if (JoseConstants.TYPE_JOSE_JSON.equals(type)) { return JOSE_JSON; + } else if (JoseConstants.TYPE_AT_JWT.equals(type)) { + return AT_JWT; } else { return valueOf(type); } diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/AbstractOAuthDataProvider.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/AbstractOAuthDataProvider.java index d43e44916b1..8a35996a968 100644 --- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/AbstractOAuthDataProvider.java +++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/AbstractOAuthDataProvider.java @@ -27,6 +27,7 @@ import java.util.Map; import jakarta.ws.rs.core.MultivaluedMap; import org.apache.cxf.jaxrs.ext.MessageContext; import org.apache.cxf.rs.security.jose.common.JoseConstants; +import org.apache.cxf.rs.security.jose.common.JoseType; import org.apache.cxf.rs.security.jose.jwt.JwtClaims; import org.apache.cxf.rs.security.jose.jwt.JwtConstants; import org.apache.cxf.rs.security.jose.jwt.JwtToken; @@ -706,7 +707,11 @@ public abstract class AbstractOAuthDataProvider implements OAuthDataProvider, Cl // It will JWS-sign (default) and/or JWE-encrypt OAuthJoseJwtProducer processor = getJwtAccessTokenProducer() == null ? new OAuthJoseJwtProducer() : getJwtAccessTokenProducer(); - return processor.processJwt(new JwtToken(jwtCliams)); + JwtToken jwt = new JwtToken(jwtCliams); + // RFC 9068 Section 2.1: JWT access tokens MUST set typ to "at+jwt" + jwt.getJwsHeaders().setType(JoseType.AT_JWT); + jwt.getJweHeaders().setType(JoseType.AT_JWT); + return processor.processJwt(jwt); } public Map<String, String> getJwtAccessTokenClaimMap() {
