Client credentials: "PublicKey wasn't found in the storage"

I’m trying to get the client credentials flow to work using a client certificate (I have verified that it works with client secret).

I first tried using a self signed certificate I created, but that didn’t work, so under Client → Client Name → Keys, I clicked on “Generate new keys and certificate” and downloaded the *.p12 file generated by Keycloak. Now, when I use this file to sign the client assertion token, I see the following error message in Keycloak logs:

PublicKey wasn't found in the storage. Requested kid: '4267C136CEB0E983C1DF179833BCA94E49DEBCE6' . Available kids: '[rx2TFOCmzEf9wOAem0EU4G2Hp-LJELt87JIlZ87wJA8]'

For some reason, the KID header was wrong. Couldn’t find the reason (I’m using Microsoft.IdentityModel, but I suppose that cannot be the reason) so, when creating the client assertion token, I removed the existing header and added the one expected by KeyCloak. But now, I’m getting two different errors.

  1. Sometimes, Keycloak reports Token reuse detected. The error message looks like this: “Token ‘785435e5-fb0c-4dc5-8a03-4971c1c188b9’ already used when authenticating client ‘Client Name’.” I know that this is not possible since the “jti” claim is different each time I send a client assertion token.
  2. Other times I get Token is not active.

I’m pretty much stuck at this point, because the error messages don’t make much sense to me. Any pointers would be greatly appreciated.

Full error log for the original error:

WARN  [org.keycloak.keys.infinispan.InfinispanPublicKeyStorageProvider] (executor-thread-576) PublicKey wasn't found in the storage. Requested kid: '4267C136CEB0E983C1DF179833BCA94E49DEBCE6' . Available kids: '[rx2TFOCmzEf9wOAem0EU4G2Hp-LJELt87JIlZ87wJA8]'
WARN  [org.keycloak.keys.infinispan.InfinispanPublicKeyStorageProvider] (executor-thread-576) Won't load the keys for model 'features_f-eic-keycloak::client::5b788eaa-0ba8-4cce-9b20-df663a129e17::keyuse::SIG' . Last request time was 1656923315
WARN  [org.keycloak.keys.infinispan.InfinispanPublicKeyStorageProvider] (executor-thread-576) PublicKey wasn't found in the storage. Requested kid: '4267C136CEB0E983C1DF179833BCA94E49DEBCE6' . Available kids: '[rx2TFOCmzEf9wOAem0EU4G2Hp-LJELt87JIlZ87wJA8]'
ERROR [org.keycloak.services] (executor-thread-576) KC-SERVICES0025: Error when validating client assertion: java.lang.RuntimeException: Signature on JWT token by client secret  failed validation
    at org.keycloak.authentication.authenticators.client.JWTClientSecretAuthenticator.authenticateClient(JWTClientSecretAuthenticator.java:173)
    at org.keycloak.authentication.ClientAuthenticationFlow.processFlow(ClientAuthenticationFlow.java:72)
    at org.keycloak.authentication.AuthenticationProcessor.authenticateClient(AuthenticationProcessor.java:901)
    at org.keycloak.protocol.oidc.utils.AuthorizeClientUtil.authorizeClient(AuthorizeClientUtil.java:51)
    at org.keycloak.protocol.oidc.endpoints.TokenEndpoint.checkClient(TokenEndpoint.java:246)
    at org.keycloak.protocol.oidc.endpoints.TokenEndpoint.processGrantRequest(TokenEndpoint.java:190)
    at jdk.internal.reflect.GeneratedMethodAccessor417.invoke(Unknown Source)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:170)
    at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:130)
    at org.jboss.resteasy.core.ResourceMethodInvoker.internalInvokeOnTarget(ResourceMethodInvoker.java:660)
    at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTargetAfterFilter(ResourceMethodInvoker.java:524)
    at org.jboss.resteasy.core.ResourceMethodInvoker.lambda$invokeOnTarget$2(ResourceMethodInvoker.java:474)
    at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:364)
    at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:476)
    at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:434)
    at org.jboss.resteasy.core.ResourceLocatorInvoker.invokeOnTargetObject(ResourceLocatorInvoker.java:192)
    at org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:152)
    at org.jboss.resteasy.core.ResourceLocatorInvoker.invokeOnTargetObject(ResourceLocatorInvoker.java:183)
    at org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:141)
    at org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:32)
    at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:492)
    at org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:261)
    at org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:161)
    at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:364)
    at org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:164)
    at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:247)
    at io.quarkus.resteasy.runtime.standalone.RequestDispatcher.service(RequestDispatcher.java:73)
    at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.dispatch(VertxRequestHandler.java:151)
    at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.handle(VertxRequestHandler.java:82)
    at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.handle(VertxRequestHandler.java:42)
    at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1212)
    at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:163)
    at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:141)
    at io.quarkus.vertx.http.runtime.StaticResourcesRecorder$2.handle(StaticResourcesRecorder.java:67)
    at io.quarkus.vertx.http.runtime.StaticResourcesRecorder$2.handle(StaticResourcesRecorder.java:55)
    at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1212)
    at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:163)
    at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:141)
    at io.quarkus.vertx.http.runtime.VertxHttpRecorder$5.handle(VertxHttpRecorder.java:380)
    at io.quarkus.vertx.http.runtime.VertxHttpRecorder$5.handle(VertxHttpRecorder.java:358)
    at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1212)
    at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:163)
    at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:141)
    at org.keycloak.quarkus.runtime.integration.web.QuarkusRequestFilter.lambda$createBlockingHandler$1(QuarkusRequestFilter.java:71)
    at io.vertx.core.impl.ContextImpl.lambda$null$0(ContextImpl.java:159)
    at io.vertx.core.impl.AbstractContext.dispatch(AbstractContext.java:100)
    at io.vertx.core.impl.ContextImpl.lambda$executeBlocking$1(ContextImpl.java:157)
    at io.quarkus.vertx.core.runtime.VertxCoreRecorder$13.runWith(VertxCoreRecorder.java:543)
    at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2449)
    at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1478)
    at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
    at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
    at java.base/java.lang.Thread.run(Thread.java:829)

ERROR [org.keycloak.services] (executor-thread-576) KC-SERVICES0017: Unknown result status
WARN  [org.keycloak.events] (executor-thread-576) type=CLIENT_LOGIN_ERROR, realmId=features_f-eic-keycloak, clientId=LiveTests, userId=null, ipAddress=195.1.83.138, error=invalid_client_credentials, grant_type=client_credentials