Hi to all.Probably i catched a bug in the keycloak authentication flow.This is my user
case:Configuration:1) I've created a new realm, say "TestRealm"2) I've
created 1 role: "testRole"3) I've created 2 users: "userTest1" and
"userTest2"4) In the role mapping tab of each user i've assigned
"testRole" to both of them5) In the credential tab of each user i've changed
their pwd
Use case:1) I try to access the account application
from: https://localhost:8444/auth/realms/TestRealm/account/2) I insert username:
userTest1 pwd: (a wrong password)
Login page displays a tooltip saying "invalid username or password"
3) Withouth any page refreshing i try to login again with second user:
username: userTest2: pwd: (whatever right or wrong password)
Keycloak catch an exception:The page displays: We're
sorry ... Invalid username or password.
<< Back to Application
Keycloak console displays this exception:13:35:27,343 WARN [org.keycloak.events] (default
task-62) type=LOGIN_ERROR, realmId=44cefb3e-1b9e-4eb0-9cfe-267e0153b0de, clientId=account,
userId=5c9afd4e-74f4-4c51-9015-d9d4a7ef883f, ipAddress=127.0.0.1,
error=invalid_user_credentials, auth_method=openid-connect, auth_type=code,
redirect_uri=https://localhost:8444/auth/realms/PROVA/account/login-redirect,
code_id=2920658d-1137-4caa-a2a2-0c530555b81d, username=userTest13:35:33,818 ERROR
[org.keycloak.authentication.AuthenticationProcessor] (default task-72) failed
authentication: USER_CONFLICT: org.keycloak.authentication.AuthenticationFlowException at
org.keycloak.authentication.AuthenticationProcessor.setAutheticatedUser(AuthenticationProcessor.java:203)
at
org.keycloak.authentication.AuthenticationProcessor$Result.setUser(AuthenticationProcessor.java:332)
at
org.keycloak.authentication.authenticators.browser.AbstractUsernameFormAuthenticator.validateUser(AbstractUsernameFormAuthenticator.java:129)
at
org.keycloak.authentication.authenticators.browser.UsernamePasswordForm.validateForm(UsernamePasswordForm.java:41)
at
org.keycloak.authentication.authenticators.browser.UsernamePasswordForm.action(UsernamePasswordForm.java:34)
at
org.keycloak.authentication.DefaultAuthenticationFlow.processAction(DefaultAuthenticationFlow.java:62)
at
org.keycloak.authentication.DefaultAuthenticationFlow.processAction(DefaultAuthenticationFlow.java:54)
at
org.keycloak.authentication.AuthenticationProcessor.authenticationAction(AuthenticationProcessor.java:692)
at
org.keycloak.services.resources.LoginActionsService.processFlow(LoginActionsService.java:307)
at
org.keycloak.services.resources.LoginActionsService.processAuthentication(LoginActionsService.java:288)
at
org.keycloak.services.resources.LoginActionsService.authenticateForm(LoginActionsService.java:334)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at
java.lang.reflect.Method.invoke(Method.java:497) at
org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:137) at
org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:296)
at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:250) at
org.jboss.resteasy.core.ResourceLocatorInvoker.invokeOnTargetObject(ResourceLocatorInvoker.java:140)
at org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:103)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:356) at
org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:179) at
org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:220)
at
org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:56)
at
org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:51)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790) at
io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:86) at
io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:130)
at
org.keycloak.services.filters.KeycloakSessionServletFilter.doFilter(KeycloakSessionServletFilter.java:59)
at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:60) at
io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:132)
at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:85) at
io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
at
io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
at
org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) at
io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:131)
at
io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) at
io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
at
io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
at
io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:58)
at
io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:72)
at
io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50)
at
io.undertow.security.handlers.SecurityInitialHandler.handleRequest(SecurityInitialHandler.java:76)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) at
org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) at
io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) at
io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:282)
at
io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:261)
at
io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:80)
at
io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:172)
at io.undertow.server.Connectors.executeRootHandler(Connectors.java:199) at
io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:774) at
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at
java.lang.Thread.run(Thread.java:745)
13:35:33,819 WARN [org.keycloak.events] (default task-72) type=LOGIN_ERROR,
realmId=44cefb3e-1b9e-4eb0-9cfe-267e0153b0de, clientId=account, userId=null,
ipAddress=127.0.0.1, error=invalid_user_credentials, auth_method=openid-connect,
auth_type=code,
redirect_uri=https://localhost:8444/auth/realms/PROVA/account/login-redirect,
code_id=2920658d-1137-4caa-a2a2-0c530555b81d, username=userTest2
I experienced this error while debugging my custom user federation provider. So i tried to
replicate it with a clean situation like described in the use case above.Debugging my
userfederation provider i could realize the real authentication flow:
When userTest1 logs in the flow starts from:
UsernamePasswordForm.action() ---> validateUser ---> ---->
UserFederationProvider.isValid() ----> ... ... ... --->
UsernamePasswordForm.validatePassword() ----> authenticate
When userTest2 logs in after userTest1 failure the flow starts from the
UserFederationProvider.isValid():
UserFederationProvider.isValid() (the AuthenticationFlowContext user is still userTest1
)---> ... ----> UsernamePasswordForm.action() ---> validateUser ---> ---->
UserFederationProvider.isValid() ----> ... ... ... --->Exception on
Context.set(user).
It seems like Context is not cleaned after the first wrong login attempt, bringing with
itself the userTest1 user object on the second one. So when keycloak tries to set the new
user object catches a USERCONFLICT exception.