Keycloak - AuthenticationFlowException: Not found serialized context in clientSession - keycloak

I am getting this exception when trying to log in from an external IDP using Keycloak.
Failed authentication: org.keycloak.authentication.AuthenticationFlowException: Not found serialized context in clientSession
at org.keycloak.authentication.authenticators.broker.AbstractIdpAuthenticator.authenticate(AbstractIdpAuthenticator.java:66)
at org.keycloak.authentication.DefaultAuthenticationFlow.processFlow(DefaultAuthenticationFlow.java:200)
at org.keycloak.authentication.AuthenticationProcessor.authenticateOnly(AuthenticationProcessor.java:853)
at org.keycloak.authentication.AuthenticationProcessor.authenticate(AuthenticationProcessor.java:722)
at org.keycloak.services.resources.LoginActionsService.processFlow(LoginActionsService.java:286)
at org.keycloak.services.resources.LoginActionsService.brokerLoginFlow(LoginActionsService.java:753)
at org.keycloak.services.resources.LoginActionsService.postBrokerLoginGet(LoginActionsService.java:687)
at sun.reflect.GeneratedMethodAccessor866.invoke(Unknown Source)
The following page is displayed when error occurs.
I know for sure that the user credentials are correct. I have also checked the token mappers for the IDP and everything seems correct.
So what could be the issue here?

I finally figured this out. I had the post login flow set to first broker login in my Identity Provider settings. It should be left blank for my Identity Provider.

Go to Realm Settings -> Login(tab)
Try to turn off the Email as username parameter.
It it will resolve your issue - then you need to create proper mapper in Mappers tab in identity provider configuration. After your new mapper will properly pass emails as usernames you can turn Email as username on.

Related

How to use two providers with same username in a realm/client in keycloak

I have keycloak instance (version 16) with one realm and two different clients.
The first client works with Open ID Connect Identity provider. It also works with public Access Type and with SSO and 2FA.
The second client works with a Custom module added from User Federation where 2FA is not possible to be used because the calls for authentication are mainly programmatically. Also, this client works with confidential Access Type.
The problem is that each client has a different external database with users, but the usernames in these databases are not unique.
And if I try to log in with the second client it works but after that, if I try to log in with the first client I can't, and vice versa. (in both clients username "notUniqueUser#email.com" is used)
The error message in this case is:
User with username notUniqueUser#email.com already exists. How do you want to continue?
“Review profile”
“Add to existing account”
Is it possible for these two clients to work both properly at the same time, when I do not have unique usernames and how should I configure it? (I find that is possible to have same email addresses but I can't find anything for usernames)
Maybe some kind of force authentication will be OK, and when the user "notUniqueUser#email.com" is already logged with the first client and I try to log in with the second, the session from the first one to be deleted and vice versa.
Depending on how your IDPs are configured you can try the following:
go to your realm
then to the IDP configuration in question
switch to Mappers
Click on Create
As a mapper type select Username teamplate Importer
in the template field and something that will make the username unique for example ${CLAIM.preferred_username}_<The Name of the IDP>
For example, if a username named 'user' logins from both 'IDP1' and 'IDP2' it will be imported into the Keycloak DB as 'user_IDP1' and 'user_IDP2', respectively.

okta OAuthError: Could not acquire access token from authorization code

I am using OKTA.
Looks like that i got an error when clicking on login button:
OAuthError: Could not acquire access token from authorization code.
My app is in LIVE. All the settings in app dashboard look correct, because I took a simple js sdk in index.html file and made it work. So Something happens on okta Size. I am using social/identity providers.
Anyone has ever used okta and reached this error?
Another hint is that their support somehow on their back-end admin panel checked and they also get another error message: "Cannot call API on behalf of this user"
I had the same issue, in my case the issue was because the security secret key didn't match with the one in the IDP database.
If you have generated manually the secrete key check that the key is created using ssh256 hash.
You can find how to generate a secrete key here
https://stackoverflow.com/a/44013730/4878365

How to detect which identity provider send a response

Currently, I'm trying to implement an OpenID Connect solution which supports multiple identity providers. I chose to use the authorization code flow for this.
When the user opens the login screen the logo's of the supported identity providers are visible. When a logo/identity provider is clicked the system will store the necessary cookies and will redirect the user to the identity provider.
The response of the identity provider contains the following information:
Authorization code
Session_state
State
Scope
Now if I want to make a token request I don't know which identity provider to use. Some things I thought of two things to solve this issue:
Using the UrlReferrer
Storing the used provider in the cookies(Encrypted).
Does anyone know how to solve this problem?
Storing the provider details in session or in cookies would be the better option I guess as you might need to use other endpoints (such as introspection, certification) later in the flow.

keycloak - realm resolution based on username (email address)

I'm working on a multi tenant project where usernames are actually their email addresses and the domain of the email serves as a tenant identifier.
Now in keycloak I'll have different realms per tenant, but I want to have a single login page for all tenants and the actual realm that will do the authentication to be somehow resolved by the username (email address).
How do I go about doing that?
I found a thread on the mailing list (that I cant find now...) that discussed the same problem. It was something along the lines of - create a main realm that will "proxy" to the others, but I'm not quite sure how to do that.
I think Michał Łazowik's answer is on the right track, but for Single-Sign-On to work, it needs to be extended a little.
Keep in mind that because of KEYCLOAK-4593 if we have > 100 realms we may have to have multiple Keycloak servers also.
We'll need:
A separate HTTP server specifically for this purpose, auth-redirector.example.com.
An algorithm to determine the Keycloak server and realm from a username (email address).
Here would be the entire OAuth2 Authorization Code Flow:
An application discovers the user wants to log in. Before multiple realms, the realm's name would be a constant, so the application would redirect to:
https://keycloak.example.com/auth/realms/realname/protocol/openid-connect/auth?$get_params
Instead, it redirects to
https://auth-redirector.example.com/?$get_params
auth-redirector determines if it itself has a valid access token for this session, perhaps having to refresh the access token first from the Keycloak server that issued it (the user could have logged out and is trying to login as a different user that is served by a different realm).
If it has an valid access token we can determine the Keycloak server and realm from the username or email address in the access token and redirect to:
https://$keycloak_server/auth/$realm/realname/protocol/openid-connect/auth?$get_params
from here, the OAuth2 Authorization Code Flow proceeds as usual.
Else if it doesn't have a a valid access token, the auth-redirector stores the original app's $get_params as session data. It presents a form to the user asking for a username. When the user submits that, we can determine the Keycloak server and realm to use and then auth-redirector itself logs in to the Keycloak server using its own $get_params. Once the auth-redirector gets a call-back, it retrieves the access+refresh token from the Keycloak server and stores them in session data. It then, finally, redirects back to that same keycloak server and realm with the callers original $get_params (from session data). And the OAuth2 Authorization Code Flow proceeds as usual.
This is definitely a hack! But I think it could work. I'd love to try it out some day, time permitting.
Other hacks/solutions are needed for other OAuth2 flows...
The idea from the mailing list is to write a service (let's say auth-redirector.example.com) that has a single input field for email, finds realm based on domain and redirects to that realm's keycloak endpoint (e.g. auth.example.com/auth/realms/realm-name/etc…) while keeping all GET params.
You can find examples of direct login/registration URLs here: https://lists.jboss.org/pipermail/keycloak-user/2016-July/007045.html
One usability problem is that users would have to provide their email twice, I have not yet found a way to pass the username via the login URL.

Shibboleth IDPv3 NameId with KerberosAuthNConfiguration

I've set up Shibboleth IDPv3 to test my SP implementation. SP sends a SAML Logon request and the user is presented with the Shibboleth IDP credentials page in which the user enters their Kerberos credentials (I've configured the Loginflow with KerberosAuthNConfiguration). The SAML response comes back with a nameId which has what looks like an encoded value. However, what I want is the NameId element to contain the username that the user used to login to the IDP credentials page.
I had a few attempts by trying to configure the beans in the various XML configuration files without any luck. Has anybody tried something similar is this even possible to achieve ?
If you look in the file saml-nameid.properties you will see the parameter idp.nameid.saml2.default. I suspect that your configuration is set to the default of urn:oasis:names:tc:SAML:2.0:nameid-format:transient which is not an encoded value, but rather a random string.
It sounds like you want to send a "persistent" identifier rather than a transient identifier. To do this,
Change idp.nameid.saml2.default to urn:oasis:names:tc:SAML:2.0:nameid-format:persistent.
Next, you will need to enable the Persistent NameID Generator in the file saml-nameid.xml.
Finally you need to set the attribute to use in your nameid via the idp.persistentId.sourceAttribute property, also in saml-nameid.properties.
Details on how to do this can be found at the Shibboleth IdP PersistentNameIDGenerationConfiguration page.