2121import org .apache .cxf .rs .security .jose .jwt .JwtToken ;
2222import org .apache .cxf .rs .security .oauth2 .client .Consumer ;
2323import org .apache .cxf .rs .security .oauth2 .common .ClientAccessToken ;
24+ import org .apache .cxf .rs .security .oauth2 .utils .OAuthConstants ;
2425import org .apache .cxf .rs .security .oidc .common .IdToken ;
2526import org .apache .cxf .rs .security .oidc .utils .OidcUtils ;
2627
@@ -44,7 +45,11 @@ public JwtToken getIdJwtToken(ClientAccessToken at, String code, Consumer client
4445 String idJwtToken = at .getParameters ().get (OidcUtils .ID_TOKEN );
4546 JwtToken jwt = getIdJwtToken (idJwtToken , client );
4647 OidcUtils .validateAccessTokenHash (at , jwt , requireAtHash );
47- OidcUtils .validateCodeHash (code , jwt , requireCodeHash );
48+ if (code != null ) {
49+ // The spec requires c_hash to be present in the id_token for hybrid flows,
50+ // but we allow it to be optional for token endpoint id_tokens
51+ OidcUtils .validateCodeHash (code , jwt , requireCodeHash || isHybridFlow (at ));
52+ }
4853 return jwt ;
4954 }
5055 public JwtToken getIdJwtToken (ClientAccessToken at , Consumer client ) {
@@ -55,6 +60,13 @@ public JwtToken getIdJwtToken(String idJwtToken, Consumer client) {
5560 validateJwtClaims (jwt .getClaims (), client .getClientId (), true );
5661 return jwt ;
5762 }
63+
64+ private boolean isHybridFlow (ClientAccessToken at ) {
65+ String responseType = at .getParameters ().get (OAuthConstants .RESPONSE_TYPE );
66+ return OidcUtils .CODE_ID_TOKEN_RESPONSE_TYPE .equals (responseType )
67+ || OidcUtils .CODE_ID_TOKEN_AT_RESPONSE_TYPE .equals (responseType );
68+ }
69+
5870 private IdToken getIdTokenFromJwt (JwtToken jwt ) {
5971 return new IdToken (jwt .getClaims ().asMap ());
6072 }
0 commit comments