I’m trying to get a First Login flow working whereby only pre-created users are allowed to log in.
MS Azure AD is used as trusted IdP. The users are created in Keycloak with username+email and without any IdP Links.
My IdP uses SAML2.0 and has mappers configured for username and email. Username is a Attribute Importer and username uses the Username Template Importer with template ${ATTRIBUTE.http://schemas.xmlsoap.org/ws/2005/05/identity/claims/onpremisessamaccountname}. I verified that both these are mapped correctly (ie, with the default First Broker
Login flow the account is created with the expected parameters).
The only way I can get existing users to link to the IdP is using “Create User If Unique” in the First Login flow, as described in the “Automatically Link Existing First Login Flow” documentation item, but that would also create user accounts for about anyone, which is not what I want.
I’ve tried to use “Automatically Set Existing User” (to set the existing user to the auth context) and then “Confirm Link Existing Account”. But here the login page returns “Invalid username or password” and the server logs contain:
Failed authentication: org.keycloak.authentication.AuthenticationFlowException: Unexpected state. There is no existing duplicated user identified in ClientSession
It seems that authSession.getAuthNote(EXISTING_USER_INFO); fails to look up the existing user, which seems to be (only?) set by IdpCreateUserIfUniqueAuthenticator.
Is this a supported flow ?
I’m using Keycloak 8.0.1, the client uses OIDC.
Thank you in advance for your help.
@mreinli I’ve tried to send a message few minutes ago, I hope that someone will answer.
–
I’ve configured Okta as IdP (I’m using SAML, but it seems that the error is not related to SAML or OpenID, nor to the type of IdP used) and then configured an Authentication flow with “Automatically Set Existing User”.
When I try to login using my IdP I receive an “Invalid username or password” error and in Keycloak log I see this exception:
[org.keycloak.services] (default task-227) KC-SERVICES0013: Failed authentication: org.keycloak.authentication.AuthenticationFlowException: Unexpected state. There is no existing duplicated user identified in ClientSession
at org.keycloak.keycloak-services@10.0.1//org.keycloak.authentication.authenticators.broker.AbstractIdpAuthenticator.getExistingUser(AbstractIdpAuthenticator.java:120)
at org.keycloak.keycloak-services@10.0.1//org.keycloak.authentication.authenticators.broker.IdpEmailVerificationAuthenticator.authenticateImpl(IdpEmailVerificationAuthenticator.java:83)
at org.keycloak.keycloak-services@10.0.1//org.keycloak.authentication.authenticators.broker.AbstractIdpAuthenticator.authenticate(AbstractIdpAuthenticator.java:76)
at org.keycloak.keycloak-services@10.0.1//org.keycloak.authentication.DefaultAuthenticationFlow.processSingleFlowExecutionModel(DefaultAuthenticationFlow.java:438)
at org.keycloak.keycloak-services@10.0.1//org.keycloak.authentication.DefaultAuthenticationFlow.processFlow(DefaultAuthenticationFlow.java:247)
at org.keycloak.keycloak-services@10.0.1//org.keycloak.authentication.AuthenticationProcessor.authenticateOnly(AuthenticationProcessor.java:976)
at org.keycloak.keycloak-services@10.0.1//org.keycloak.services.resources.LoginActionsService$1.authenticateOnly(LoginActionsService.java:792)
at org.keycloak.keycloak-services@10.0.1//org.keycloak.authentication.AuthenticationProcessor.authenticate(AuthenticationProcessor.java:838)
at org.keycloak.keycloak-services@10.0.1//org.keycloak.services.resources.LoginActionsService.processFlow(LoginActionsService.java:313)
at org.keycloak.keycloak-services@10.0.1//org.keycloak.services.resources.LoginActionsService.brokerLoginFlow(LoginActionsService.java:822)
at org.keycloak.keycloak-services@10.0.1//org.keycloak.services.resources.LoginActionsService.firstBrokerLoginGet(LoginActionsService.java:716)
at jdk.internal.reflect.GeneratedMethodAccessor1103.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)
[...]
The same if I use “Confirm Link Existing Account” and “Verify Existing Account By Email”. The only way for login is to manual link the Keycloak user with my IdP (by create an Identity Provider Links in user settings).
It seems that there is something wrong during the lookup of the existing user.
In SAML assertion I’m sending the email address as NameID, and I’m sending also firstName, lastName and email as additional attribute.
It’s a bug in keycloak and they seem to be a reluctant to fix it for whatever reason. I have very few users so I solved it by manually querying the idp for the information keycloak uses and then copying it into the relevant fields in the UI. So there is no sign up process for my users I just make them myself. Obviously that’s a poor solution though, what we really need is someone to take over that PR and persuade the maintainers to merge it.
I figured out that the userId field has to match the value in the subject claim and the username field has to match the preferred_username claim of the token issued from the IdP.
I am not sure if other user attributes of the Keycloak user have to match. Is this documented somewhere or do you know where to look at in the source code?
In our logs, we found out that we had configured Detect Existing Broker User and Automatically Set Existing User in the wrong order.
This is the order as correctly described in the documentation. But the error message doesn’t make this obvious. In particular error=invalid_user_credentials set us initially on the wrong track.
The scenario you describe is not the topic of this discussion:
I’m trying to get a First Login flow working whereby only pre-created users are allowed to log in.
I don’t have experience with supporting both user linking and creation, but it sounds like you would need to include “Create user if unique” in your flow.
The scenario I described does look a little different from this discussion. Because this discussion only allows the business system to create users and the idp to update them when idp log in for the first time. What I want to achieve is that when the user does not exist, the user can be created by both the business system and the idp, and then both can log in.
I tried to add “Create user if unique”, when business system has create user, idp login will error, beacause idp can’t create user.
I am replying under this discussion because it is a somewhat similar scenario to mine and I saw your response. If you have time and are willing, I would like to discuss with you.