This is an automated email from the ASF dual-hosted git repository.

coheigea pushed a commit to branch coheigea/c_hash
in repository https://gitbox.apache.org/repos/asf/cxf.git

commit 8d2db70781a87a20f055f693c10017d64179ad12
Author: Colm O hEigeartaigh <[email protected]>
AuthorDate: Wed Jun 17 13:16:50 2026 +0100

    Require c_hash for the hybrid case
---
 .../cxf/rs/security/oidc/idp/IdTokenResponseFilter.java    |  3 +++
 .../org/apache/cxf/rs/security/oidc/rp/IdTokenReader.java  | 14 +++++++++++++-
 .../cxf/systest/jaxrs/security/oidc/OIDCFlowTest.java      |  2 ++
 3 files changed, 18 insertions(+), 1 deletion(-)

diff --git 
a/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/idp/IdTokenResponseFilter.java
 
b/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/idp/IdTokenResponseFilter.java
index 674371ea26e..59bba1a6d73 100644
--- 
a/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/idp/IdTokenResponseFilter.java
+++ 
b/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/idp/IdTokenResponseFilter.java
@@ -56,6 +56,9 @@ public class IdTokenResponseFilter extends 
OAuthServerJoseJwtProducer implements
         if (ct.getApprovedScope() == null || 
!ct.getApprovedScope().contains(OidcUtils.OPENID_SCOPE)) {
             return;
         }
+        if (st.getResponseType() != null) {
+            ct.getParameters().put(OAuthConstants.RESPONSE_TYPE, 
st.getResponseType());
+        }
         String idToken = getProcessedIdToken(st);
         if (idToken != null) {
             ct.getParameters().put(OidcUtils.ID_TOKEN, idToken);
diff --git 
a/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/rp/IdTokenReader.java
 
b/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/rp/IdTokenReader.java
index a28947d6627..38e0488e838 100644
--- 
a/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/rp/IdTokenReader.java
+++ 
b/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/rp/IdTokenReader.java
@@ -21,6 +21,7 @@ package org.apache.cxf.rs.security.oidc.rp;
 import org.apache.cxf.rs.security.jose.jwt.JwtToken;
 import org.apache.cxf.rs.security.oauth2.client.Consumer;
 import org.apache.cxf.rs.security.oauth2.common.ClientAccessToken;
+import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants;
 import org.apache.cxf.rs.security.oidc.common.IdToken;
 import org.apache.cxf.rs.security.oidc.utils.OidcUtils;
 
@@ -44,7 +45,11 @@ public class IdTokenReader extends OidcClaimsValidator {
         String idJwtToken = at.getParameters().get(OidcUtils.ID_TOKEN);
         JwtToken jwt = getIdJwtToken(idJwtToken, client);
         OidcUtils.validateAccessTokenHash(at, jwt, requireAtHash);
-        OidcUtils.validateCodeHash(code, jwt, requireCodeHash);
+        if (code != null) {
+            // The spec requires c_hash to be present in the id_token for 
hybrid flows,
+            // but we allow it to be optional for token endpoint id_tokens
+            OidcUtils.validateCodeHash(code, jwt, requireCodeHash || 
isHybridFlow(at));
+        }
         return jwt;
     }
     public JwtToken getIdJwtToken(ClientAccessToken at, Consumer client) {
@@ -55,6 +60,13 @@ public class IdTokenReader extends OidcClaimsValidator {
         validateJwtClaims(jwt.getClaims(), client.getClientId(), true);
         return jwt;
     }
+
+    private boolean isHybridFlow(ClientAccessToken at) {
+        String responseType = 
at.getParameters().get(OAuthConstants.RESPONSE_TYPE);
+        return OidcUtils.CODE_ID_TOKEN_RESPONSE_TYPE.equals(responseType)
+            || OidcUtils.CODE_ID_TOKEN_AT_RESPONSE_TYPE.equals(responseType);
+    }
+
     private IdToken getIdTokenFromJwt(JwtToken jwt) {
         return new IdToken(jwt.getClaims().asMap());
     }
diff --git 
a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oidc/OIDCFlowTest.java
 
b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oidc/OIDCFlowTest.java
index cd03952ea73..489e2eea5be 100644
--- 
a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oidc/OIDCFlowTest.java
+++ 
b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oidc/OIDCFlowTest.java
@@ -672,6 +672,8 @@ public class OIDCFlowTest extends 
AbstractBusClientServerTestBase {
             OAuth2TestUtils.getAccessTokenWithAuthorizationCode(client, code);
         assertNotNull(accessToken.getTokenKey());
         assertTrue(accessToken.getApprovedScope().contains("openid"));
+        assertEquals(OidcUtils.CODE_ID_TOKEN_RESPONSE_TYPE,
+                     
accessToken.getParameters().get(OAuthConstants.RESPONSE_TYPE));
 
         // Check id_token from the token endpoint
         idToken = accessToken.getParameters().get("id_token");

Reply via email to