spring-projects / spring-authorization-server

Spring Authorization Server
https://spring.io/projects/spring-authorization-server
Apache License 2.0
4.78k stars 1.25k forks source link

RegisteredClient's idTokenSignatureAlgorithm only accepts SignatureAlgorithm #1585

Closed jukkaleh-atoz closed 2 months ago

jukkaleh-atoz commented 3 months ago

Describe the bug I have a client that expects JWT to be signed with symmetric secret using HMAC SHA-256 (HS256). I'm not able to pass MacAlgorithm to TokenSettings.Builder.idTokenSignatureAlgorithm since it only accepts SignatureAlgorithm

To Reproduce Try to register client with HS256 signing algorithm

Expected behavior

MacAlgorithm and SignatureAlgorithm both implement the same interface JwsAlgorithm.

  1. Change Builder#idTokenSignatureAlgorithm to accept any JwsAlgorithm

or

  1. Add overloaded function idTokenSignatureAlgorithm that accepts MacAlgorithm.

Sample

 final RegisteredClient client= RegisteredClient.withId(UUID.randomUUID().toString())
  ...
      .tokenSettings(TokenSettings.builder()
          .idTokenSignatureAlgorithm(MacAlgorithm.HS256)
          .build()
  ...
      .build();

Workaround

Use OAuth2TokenCustomizer to change algorithm

    @Bean
    public JWKSource<SecurityContext> jwkSource() {
        // Create a symmetric key
        SecretKeySpec secretKeySpec = new SecretKeySpec("shared-secret".getBytes(StandardCharsets.UTF_8), JWSAlgorithm.HS256.getName());

        // Create a JWK with the symmetric key
        OctetSequenceKey jwk = new OctetSequenceKey.Builder(secretKeySpec)
                .algorithm(JWSAlgorithm.HS256)
                .keyID(UUID.randomUUID().toString())
                .build();

        // Create a JWK set with the JWK
        JWKSet jwkSet = new JWKSet(jwk);

        // Return an immutable JWK source backed by the JWK set
        return new ImmutableJWKSet<>(jwkSet);
    }

    @Bean
    public OAuth2TokenCustomizer<JwtEncodingContext> tokenCustomizer() {
     return (context -> {
         if (context.getRegisteredClient().getClientId().equals("client")) {
             context.getJwsHeader().algorithm(MacAlgorithm.HS256);
         }
     });
    }
jgrandja commented 2 months ago

@jukkaleh-atoz

I'm not able to pass MacAlgorithm to TokenSettings.Builder.idTokenSignatureAlgorithm since it only accepts SignatureAlgorithm

Please see 2. Client Metadata:

id_token_signed_response_alg OPTIONAL. JWS alg algorithm [JWA] REQUIRED for signing the ID Token issued to this Client. The value none MUST NOT be used as the ID Token alg value unless the Client uses only Response Types that return no ID Token from the Authorization Endpoint (such as when only using the Authorization Code Flow). The default, if omitted, is RS256. The public key for validating the signature is provided by retrieving the JWK Set referenced by the jwks_uri element from OpenID Connect Discovery 1.0 [OpenID.Discovery].

Notice the text in bold - the public key is used to validate the signature. This implies asymmetric keys and the default is RS256.

For symmetric keys, see 3.1.3.7. ID Token Validation:

  1. If the JWT alg Header Parameter uses a MAC based algorithm such as HS256, HS384, or HS512, the octets of the UTF-8 [RFC3629] representation of the client_secret corresponding to the client_id

The client_secret is used as the symmetric key.

I'm going to close this as TokenSettings.IdTokenSignatureAlgorithm is expected to be a SignatureAlgorithm.