keycloak / keycloak

Open Source Identity and Access Management For Modern Applications and Services
https://www.keycloak.org
Apache License 2.0
22.78k stars 6.68k forks source link

client-jwt ES256 error when doing CODE_TO_TOKEN #33820

Open Typhlos opened 1 day ago

Typhlos commented 1 day ago

Before reporting an issue

Area

oidc

Describe the bug

When setting up an oidc client using Signed JWT as the authentication method and ES256 as the algorithm, importing the JWKS file works fine. But when I try authenticating in this app, keycloak returns a CODE_TO_TOKEN_ERROR and throws an exception:

Oct 11 12:06:32 keycloak kc.sh[1328]: 2024-10-11 12:06:32,519 WARN  [org.keycloak.events] (executor-thread-79) type="CODE_TO_TOKEN_ERROR", realmId="xxx", realmName="xxx", clientId="xxx", userId="null", ipAddress="xxx", error="invalid_client_credentials", grant_type="authorization_code"
Oct 11 12:06:32 keycloak kc.sh[1328]: 2024-10-11 12:06:32,552 ERROR [org.keycloak.services] (executor-thread-79) KC-SERVICES0025: Error when validating client assertion: java.lang.RuntimeException: Error when loading public keys: java.lang.RuntimeException: org.keycloak.common.util.PemException: java.security.spec.InvalidKeySpecException: encoded key spec not recognized: algorithm identifier 1.2.840.10045.2.1 in key not recognised
Oct 11 12:06:32 keycloak kc.sh[1328]:         at org.keycloak.keys.infinispan.InfinispanPublicKeyStorageProvider.reloadKeys(InfinispanPublicKeyStorageProvider.java:242)
Oct 11 12:06:32 keycloak kc.sh[1328]:         at org.keycloak.keys.infinispan.InfinispanPublicKeyStorageProvider.getPublicKey(InfinispanPublicKeyStorageProvider.java:147)
Oct 11 12:06:32 keycloak kc.sh[1328]:         at org.keycloak.keys.loader.PublicKeyStorageManager.getClientPublicKeyWrapper(PublicKeyStorageManager.java:57)
Oct 11 12:06:32 keycloak kc.sh[1328]:         at org.keycloak.keys.loader.PublicKeyStorageManager.getClientPublicKey(PublicKeyStorageManager.java:43)
Oct 11 12:06:32 keycloak kc.sh[1328]:         at org.keycloak.authentication.authenticators.client.JWTClientAuthenticator.getSignatureValidationKey(JWTClientAuthenticator.java:123)
Oct 11 12:06:32 keycloak kc.sh[1328]:         at org.keycloak.authentication.authenticators.client.JWTClientAuthenticator.authenticateClient(JWTClientAuthenticator.java:85)
Oct 11 12:06:32 keycloak kc.sh[1328]:         at org.keycloak.authentication.ClientAuthenticationFlow.processFlow(ClientAuthenticationFlow.java:72)
Oct 11 12:06:32 keycloak kc.sh[1328]:         at org.keycloak.authentication.AuthenticationProcessor.authenticateClient(AuthenticationProcessor.java:918)
Oct 11 12:06:32 keycloak kc.sh[1328]:         at org.keycloak.protocol.oidc.utils.AuthorizeClientUtil.authorizeClient(AuthorizeClientUtil.java:49)
Oct 11 12:06:32 keycloak kc.sh[1328]:         at org.keycloak.protocol.oidc.endpoints.TokenEndpoint.checkClient(TokenEndpoint.java:169)
Oct 11 12:06:32 keycloak kc.sh[1328]:         at org.keycloak.protocol.oidc.endpoints.TokenEndpoint.processGrantRequest(TokenEndpoint.java:135)
Oct 11 12:06:32 keycloak kc.sh[1328]:         at org.keycloak.protocol.oidc.endpoints.TokenEndpoint$quarkusrestinvoker$processGrantRequest_6408e15340992839b66447750c221d9aaa837bd7.invoke(Unknown Source)
Oct 11 12:06:32 keycloak kc.sh[1328]:         at org.jboss.resteasy.reactive.server.handlers.InvocationHandler.handle(InvocationHandler.java:29)
Oct 11 12:06:32 keycloak kc.sh[1328]:         at io.quarkus.resteasy.reactive.server.runtime.QuarkusResteasyReactiveRequestContext.invokeHandler(QuarkusResteasyReactiveRequestContext.java:141)
Oct 11 12:06:32 keycloak kc.sh[1328]:         at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:147)
Oct 11 12:06:32 keycloak kc.sh[1328]:         at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:582)
Oct 11 12:06:32 keycloak kc.sh[1328]:         at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2513)
Oct 11 12:06:32 keycloak kc.sh[1328]:         at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1538)
Oct 11 12:06:32 keycloak kc.sh[1328]:         at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
Oct 11 12:06:32 keycloak kc.sh[1328]:         at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
Oct 11 12:06:32 keycloak kc.sh[1328]:         at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
Oct 11 12:06:32 keycloak kc.sh[1328]:         at java.base/java.lang.Thread.run(Thread.java:1583)
Oct 11 12:06:32 keycloak kc.sh[1328]: Caused by: java.util.concurrent.ExecutionException: java.lang.RuntimeException: org.keycloak.common.util.PemException: java.security.spec.InvalidKeySpecException: encoded key spec not recognized: algorithm identifier 1.2.840.10045.2.1 in key not recognised
Oct 11 12:06:32 keycloak kc.sh[1328]:         at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122)
Oct 11 12:06:32 keycloak kc.sh[1328]:         at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191)
Oct 11 12:06:32 keycloak kc.sh[1328]:         at org.keycloak.keys.infinispan.InfinispanPublicKeyStorageProvider.reloadKeys(InfinispanPublicKeyStorageProvider.java:240)
Oct 11 12:06:32 keycloak kc.sh[1328]:         ... 21 more
Oct 11 12:06:32 keycloak kc.sh[1328]: Caused by: java.lang.RuntimeException: org.keycloak.common.util.PemException: java.security.spec.InvalidKeySpecException: encoded key spec not recognized: algorithm identifier 1.2.840.10045.2.1 in key not recognised
Oct 11 12:06:32 keycloak kc.sh[1328]:         at org.keycloak.models.utils.KeycloakModelUtils.getPublicKey(KeycloakModelUtils.java:118)
Oct 11 12:06:32 keycloak kc.sh[1328]:         at org.keycloak.keys.loader.ClientPublicKeyLoader.getSignatureValidationKey(ClientPublicKeyLoader.java:119)
Oct 11 12:06:32 keycloak kc.sh[1328]:         at org.keycloak.keys.loader.ClientPublicKeyLoader.loadKeys(ClientPublicKeyLoader.java:82)
Oct 11 12:06:32 keycloak kc.sh[1328]:         at org.keycloak.keys.infinispan.InfinispanPublicKeyStorageProvider$WrapperCallable.call(InfinispanPublicKeyStorageProvider.java:282)
Oct 11 12:06:32 keycloak kc.sh[1328]:         at org.keycloak.keys.infinispan.InfinispanPublicKeyStorageProvider$WrapperCallable.call(InfinispanPublicKeyStorageProvider.java:262)
Oct 11 12:06:32 keycloak kc.sh[1328]:         at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
Oct 11 12:06:32 keycloak kc.sh[1328]:         at org.keycloak.keys.infinispan.InfinispanPublicKeyStorageProvider.reloadKeys(InfinispanPublicKeyStorageProvider.java:234)
Oct 11 12:06:32 keycloak kc.sh[1328]:         ... 21 more
Oct 11 12:06:32 keycloak kc.sh[1328]: Caused by: org.keycloak.common.util.PemException: java.security.spec.InvalidKeySpecException: encoded key spec not recognized: algorithm identifier 1.2.840.10045.2.1 in key not recognised
Oct 11 12:06:32 keycloak kc.sh[1328]:         at org.keycloak.common.crypto.PemUtilsProvider.decodePublicKey(PemUtilsProvider.java:92)
Oct 11 12:06:32 keycloak kc.sh[1328]:         at org.keycloak.common.crypto.PemUtilsProvider.decodePublicKey(PemUtilsProvider.java:74)
Oct 11 12:06:32 keycloak kc.sh[1328]:         at org.keycloak.common.util.PemUtils.decodePublicKey(PemUtils.java:65)
Oct 11 12:06:32 keycloak kc.sh[1328]:         at org.keycloak.models.utils.KeycloakModelUtils.getPublicKey(KeycloakModelUtils.java:116)
Oct 11 12:06:32 keycloak kc.sh[1328]:         ... 27 more
Oct 11 12:06:32 keycloak kc.sh[1328]: Caused by: java.security.spec.InvalidKeySpecException: encoded key spec not recognized: algorithm identifier 1.2.840.10045.2.1 in key not recognised
Oct 11 12:06:32 keycloak kc.sh[1328]:         at org.bouncycastle.jcajce.provider.asymmetric.util.BaseKeyFactorySpi.engineGeneratePublic(Unknown Source)
Oct 11 12:06:32 keycloak kc.sh[1328]:         at org.bouncycastle.jcajce.provider.asymmetric.rsa.KeyFactorySpi.engineGeneratePublic(Unknown Source)
Oct 11 12:06:32 keycloak kc.sh[1328]:         at java.base/java.security.KeyFactory.generatePublic(KeyFactory.java:345)
Oct 11 12:06:32 keycloak kc.sh[1328]:         at org.keycloak.common.util.DerUtils.decodePublicKey(DerUtils.java:69)
Oct 11 12:06:32 keycloak kc.sh[1328]:         at org.keycloak.common.crypto.PemUtilsProvider.decodePublicKey(PemUtilsProvider.java:90)
Oct 11 12:06:32 keycloak kc.sh[1328]:         ... 30 more

Version

25.0.5

Regression

Expected behavior

The oidc client correctly authenticates against Keycloak using a signed JWT and ES256 algorithm.

Actual behavior

Keycloak throws an exception and returns CODE_TO_TOKEN_ERROR.

How to Reproduce?

Create an oidc client with Signed JWT and ES256 and authenticate on this oidc client.

Anything else?

This issue seems to have been fixed with Keycloak 19, see #12152 and #11121, but it seems to have come back.

Typhlos commented 1 day ago

It seems that the bouncycastle provider loaded is RSA even if we want ECC here: Oct 11 12:06:32 keycloak kc.sh[1328]: at org.bouncycastle.jcajce.provider.asymmetric.rsa.KeyFactorySpi.engineGeneratePublic(Unknown Source)

Typhlos commented 1 day ago

I believe it might be due to this line https://github.com/keycloak/keycloak/blob/ee56ea9923533a9096a91810fbafc79464c206c0/common/src/main/java/org/keycloak/common/crypto/PemUtilsProvider.java#L74 where "RSA" type is hardcoded.* Oct 11 12:06:32 keycloak kc.sh[1328]: at org.keycloak.common.crypto.PemUtilsProvider.decodePublicKey(PemUtilsProvider.java:74) This line is called by https://github.com/keycloak/keycloak/blob/main/server-spi-private/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java#L117 where there is no type provided. Hence why the decodePublicKey method with RSA hardcoded is called. Please note that I'm not really familiar with Keycloak codebase and I'm trying to work from the stack trace so I might be wrong.