spring-projects / spring-security

Spring Security
http://spring.io/projects/spring-security
Apache License 2.0
8.8k stars 5.9k forks source link

JWKMatcher created by NimbusJwtEncoder fails to detect signing key #10807

Closed rgala closed 2 years ago

rgala commented 2 years ago

When a key has Digital Signature and Key Encipherment usages, NimbusJwtEncoder fails to detect a key, cause it expects it have KeyUse.SIGNATURE extension, however the KeyUse detected by com.nimbusds.jose.jwk.KeyUse from(final X509Certificate cert) method for such certificate is KeyUse.ENCRYPTION:

  // digitalSignature && keyEncipherment
  // (e.g. RSA TLS certificate for authenticated encryption)
  if (cert.getKeyUsage()[0] && cert.getKeyUsage()[2]) {
      return KeyUse.ENCRYPTION;
  }

This leads to org.springframework.security.oauth2.jwt.JwtEncodingException: An error occurred while attempting to encode the Jwt: Failed to select a JWK signing key exception because the JWKMatcher is build to only expect KeyUse.SIGNATURE:

      return new JWKMatcher.Builder()
              .keyType(KeyType.forAlgorithm(jwsAlgorithm))
              .keyID(headers.getKeyId())
              .keyUses(KeyUse.SIGNATURE, null)
              .algorithms(jwsAlgorithm, null)
              .x509CertSHA256Thumbprint(Base64URL.from(headers.getX509SHA256Thumbprint()))
              .build();
  }

I believe the JWKMatcher should be build with both KeyUse.SIGNATURE and KeyUse.ENCRYPTION though there is a risk that signing may fail in situations when a key has Key Encipherment usage but it does not have Digital Signature usage.

rgala commented 2 years ago

I have asked people responsible for Nimbus library and it looks like there is a workaround for this:

https://bitbucket.org/connect2id/nimbus-jose-jwt/issues/461/issue-with-key-having-digital-signature

jgrandja commented 2 years ago

@rgala

When a key has Digital Signature and Key Encipherment usages, NimbusJwtEncoder fails to detect a key, cause it expects it have KeyUse.SIGNATURE extension

The current behaviour is correct. As per javadoc for NimbusJwtEncoder:

An implementation of a {@link JwtEncoder} that encodes a JSON Web Token (JWT) using the JSON Web Signature (JWS) Compact Serialization format. The private/secret key used for signing the JWS is supplied by the {@code com.nimbusds.jose.jwk.source.JWKSource} provided via the constructor.

The current implementation ONLY supports JWS and does not support JWE. This MAY be introduced at a later point via gh-4435.

I'm going to close this as works-as-designed.