Martin Fischer
Martin Fischer

Reputation: 649

Keycloak SPNEGO Exception RC4 with HMAC

I have running a Keycloak instance via Docker. I want to use Kerberos Authentication. However, it seems to use a wrong encryption method. When trying to login via Keycloak on a Windows Kerberos PC, I get following Exception in Keycloak logs:

Debug is  true storeKey true useTicketCache false useKeyTab true doNotPrompt true ticketCache is null isInitiator false KeyTab is /tmp/key.tab refreshKrb5Config is false principal is HTTP/[email protected] tryFirstPass is false useFirstPass is false storePass is false clearPass is false
principal is HTTP/[email protected]
Will use keytab
Commit Succeeded 

2023-04-11 14:45:16,117 WARN  [org.keycloak.federation.kerberos.impl.SPNEGOAuthenticator] (executor-thread-0) SPNEGO login failed: java.security.PrivilegedActionException: GSSException: Failure unspecified at GSS-API level (Mechanism level: Encryption type RC4 with HMAC is not supported/enabled)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:716)
        at java.base/javax.security.auth.Subject.doAs(Subject.java:439)
        at org.keycloak.federation.kerberos.impl.SPNEGOAuthenticator.authenticate(SPNEGOAuthenticator.java:68)
        at org.keycloak.storage.ldap.LDAPStorageProvider.authenticate(LDAPStorageProvider.java:735)
        at org.keycloak.storage.UserStorageManager.lambda$getUserByCredential$3(UserStorageManager.java:148)
        at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
        at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
        at java.base/java.util.stream.StreamSpliterators$WrappingSpliterator.tryAdvance(StreamSpliterators.java:300)
        at java.base/java.util.stream.Streams$ConcatSpliterator.tryAdvance(Streams.java:720)
        at java.base/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:129)
        at java.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:527)
        at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:513)
        at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
        at java.base/java.util.stream.FindOps$FindOp.evaluateSequential(FindOps.java:150)
        at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
        at java.base/java.util.stream.ReferencePipeline.findFirst(ReferencePipeline.java:647)
        at org.keycloak.storage.UserStorageManager.getUserByCredential(UserStorageManager.java:150)
        at org.keycloak.models.cache.infinispan.UserCacheSession.getUserByCredential(UserCacheSession.java:550)
        at org.keycloak.authentication.authenticators.browser.SpnegoAuthenticator.authenticate(SpnegoAuthenticator.java:88)
        at org.keycloak.authentication.DefaultAuthenticationFlow.processSingleFlowExecutionModel(DefaultAuthenticationFlow.java:445)
        at org.keycloak.authentication.DefaultAuthenticationFlow.processFlow(DefaultAuthenticationFlow.java:271)
        at org.keycloak.authentication.AuthenticationProcessor.authenticateOnly(AuthenticationProcessor.java:1025)
        at org.keycloak.authentication.AuthenticationProcessor.authenticate(AuthenticationProcessor.java:887)
        at org.keycloak.protocol.AuthorizationEndpointBase.handleBrowserAuthenticationRequest(AuthorizationEndpointBase.java:153)
        at org.keycloak.protocol.oidc.endpoints.AuthorizationEndpoint.buildAuthorizationCodeAuthorizationResponse(AuthorizationEndpoint.java:363)
        at org.keycloak.protocol.oidc.endpoints.AuthorizationEndpoint.process(AuthorizationEndpoint.java:219)
        at org.keycloak.protocol.oidc.endpoints.AuthorizationEndpoint.access$300(AuthorizationEndpoint.java:69)
        at org.keycloak.protocol.oidc.endpoints.AuthorizationEndpoint$1.runInternal(AuthorizationEndpoint.java:140)
        at org.keycloak.common.util.ResponseSessionTask.run(ResponseSessionTask.java:67)
        at org.keycloak.common.util.ResponseSessionTask.run(ResponseSessionTask.java:44)
        at org.keycloak.models.utils.KeycloakModelUtils.runJobInRetriableTransaction(KeycloakModelUtils.java:299)
        at org.keycloak.protocol.oidc.endpoints.AuthorizationEndpoint.processInRetriableTransaction(AuthorizationEndpoint.java:132)
        at org.keycloak.protocol.oidc.endpoints.AuthorizationEndpoint.buildGet(AuthorizationEndpoint.java:117)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:568)
        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:1284)
        at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:173)
        at io.vertx.ext.web.impl.RoutingContextWrapper.next(RoutingContextWrapper.java:200)
        at io.quarkus.vertx.http.runtime.StaticResourcesRecorder$2.handle(StaticResourcesRecorder.java:84)
        at io.quarkus.vertx.http.runtime.StaticResourcesRecorder$2.handle(StaticResourcesRecorder.java:71)
        at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1284)
        at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:173)
        at io.vertx.ext.web.impl.RoutingContextWrapper.next(RoutingContextWrapper.java:200)
        at io.quarkus.vertx.http.runtime.VertxHttpRecorder$6.handle(VertxHttpRecorder.java:430)
        at io.quarkus.vertx.http.runtime.VertxHttpRecorder$6.handle(VertxHttpRecorder.java:408)
        at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1284)
        at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:173)
        at io.vertx.ext.web.impl.RoutingContextWrapper.next(RoutingContextWrapper.java:200)
        at org.keycloak.quarkus.runtime.integration.web.QuarkusRequestFilter.lambda$createBlockingHandler$0(QuarkusRequestFilter.java:82)
        at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:576)
        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:833)
Caused by: GSSException: Failure unspecified at GSS-API level (Mechanism level: Encryption type RC4 with HMAC is not supported/enabled)
        at java.security.jgss/sun.security.jgss.krb5.Krb5Context.acceptSecContext(Krb5Context.java:864)
        at java.security.jgss/sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:361)
        at java.security.jgss/sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:303)
        at java.security.jgss/sun.security.jgss.spnego.SpNegoContext.GSS_acceptSecContext(SpNegoContext.java:908)
        at java.security.jgss/sun.security.jgss.spnego.SpNegoContext.acceptSecContext(SpNegoContext.java:555)
        at java.security.jgss/sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:361)
        at java.security.jgss/sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:303)
        at org.keycloak.federation.kerberos.impl.SPNEGOAuthenticator.establishContext(SPNEGOAuthenticator.java:169)
        at org.keycloak.federation.kerberos.impl.SPNEGOAuthenticator$AcceptSecContext.run(SPNEGOAuthenticator.java:132)
        at org.keycloak.federation.kerberos.impl.SPNEGOAuthenticator$AcceptSecContext.run(SPNEGOAuthenticator.java:122)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:712)
        ... 80 more
Caused by: KrbException: Encryption type RC4 with HMAC is not supported/enabled
        at java.security.jgss/sun.security.krb5.EncryptionKey.findKey(EncryptionKey.java:544)
        at java.security.jgss/sun.security.krb5.KrbApReq.authenticate(KrbApReq.java:273)
        at java.security.jgss/sun.security.krb5.KrbApReq.<init>(KrbApReq.java:149)
        at java.security.jgss/sun.security.jgss.krb5.InitSecContextToken.<init>(InitSecContextToken.java:139)
        at java.security.jgss/sun.security.jgss.krb5.Krb5Context.acceptSecContext(Krb5Context.java:837)
        ... 90 more

                [Krb5LoginModule]: Entering logout
                [Krb5LoginModule]: logged out Subject

I have Keycloak v21.0.2 deployed. Why is the latest version trying to do some outdated RC4-HMAC encryption?

However, my key tab only supports aes256-cts-hmac-sha1-96, aes256-cts-hmac-sha1-96 but was generated with /crypto all.

How to configure Keycloak to use AES for Kerberos? Or what to do to resolve this issue?

Upvotes: 1

Views: 1485

Answers (2)

dedek
dedek

Reputation: 8311

In my case, keycloak was not reading the krb5.conf file containing:

[libdefaults]
    ...
    allow_weak_crypto = true

I had to add the path to keycloak java system property: java.security.krb5.conf=/the/path/to/krb5.conf

This is what I added to my keycloak Dockerfile:

...
ENV JAVA_OPTS_APPEND="-Djava.security.krb5.conf=/the/path/to/krb5.conf"
...

Caution! allow_weak_crypto = true is a security flaw, try to configure kerberos to use strong cryptography instead...

Upvotes: 0

Timur
Timur

Reputation: 1

Try to run Keycloak with "--features=kerberos" build option. For example:

docker run --name mykeycloak -p 8080:8080 -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=change_me quay.io/keycloak/keycloak:latest start --db=postgres --features=kerberos --db-url=<JDBC-URL> --db-username=<DB-USER> --db-password=<DB-PASSWORD>

Upvotes: 0

Related Questions