keycloak / keycloak

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

Keycloak SPNEGO Exception RC4 with HMAC #19822

Closed prutheus closed 1 year ago

prutheus commented 1 year ago

Before reporting an issue

Area

token-exchange

Describe the bug

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/my.domain.com@DOMAIN.COM tryFirstPass is false useFirstPass is false storePass is false clearPass is false
principal is HTTP/my.domain.com@DOMAIN.COM
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?

Version

21.0.2

Expected behavior

Kerberos authentication works as it uses AES

Actual behavior

Kerberos authentication fails with KrbException: Encryption type RC4 with HMAC is not supported/enabled

How to Reproduce?

/-

Anything else?

No response

rmartinc commented 1 year ago

Hi @prutheus!

I think your problem is that the new JDK does not support RC4. Try using allow_weak_crypto = true in the krb5.conf to allow it. The keycloak does not select the alg to connect to the AD/Kerberos server. That depends on the keytab and configuration on the kerberos server. Usually you need to configure something in the AD for that user and regenerate the keytab. See for example this thread: https://stackoverflow.com/questions/70774313/jdk-17-java-17-kerberos-authentication-fail

Nevertheless try using keycloak user group instead of issues for these kind of questions. Issues are intended for bugs that are reproducible and devs can start working on them.

mposolda commented 1 year ago

@rmartinc Thanks for the hint to the user.

I am closing as this doesn't look like a Keycloak issue, but rather related to the platform and/or Kerberos configuration. If you still think that it is Keycloak issue, please add the configuration of your krb5.conf files (at least the encryption algorithms used) as well as your KDC configuration. Also please add the java version (and vendor) you use. Also note you can enable some additional logging as described in the troubleshooting section https://www.keycloak.org/docs/latest/server_admin/index.html#troubleshooting