This is an automated email from the ASF dual-hosted git repository.
reta pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cxf.git
The following commit(s) were added to refs/heads/main by this push:
new 1f4e57ff6df RFC 9068: Set typ header to at+jwt for JWT access tokens
(#2948)
1f4e57ff6df is described below
commit 1f4e57ff6df5bb6c6e9d864ae5699d55ce5d3436
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 1bc318b8342..3c1dac23595 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 26f74928490..a78f0d9df87 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;
@@ -669,7 +670,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() {