Keycloak same username in multiple federations - authentication

I have two user federations in one realm (different active directories). Because both are completely independent, in occurs that the same username is used.
In Microsoft Applications you can use something like "ad1\ttestuser" and "ad2\ttestuser". Is there a way I can configure Keycloak to choose the user federation on login? A solution would be to add a prefix to the username in the mapper but there is no way to do it.

Is there a way I can configure Keycloak to choose the user federation
on login?
You could create a different realm per user federation that you want your users to be able to explicitly authentication against. Then you configure each user federation in its own realm. Finally,
you configured those realms to do identity brokering against the original realm.
The login page would look something like:
You can have a look a this answer which describes this setup in more detail.

Related

keycloak managed password with federated users

Is it possible to manage the password by keycloak with federated users? I have users
federated from external database and currently also the password is being checked from the external database.
Is there a possibility to register a password in keycloak for the user just after that user is created in the external database and then federated to keycloak?
My motivation is having the built in password reset functionality of keycloak not building extra SPI code for this on federated users.
It is not really clear from your question, but since you have federated users from an external database, I assume you have implemented your custom UserStorageProvider. You are also validating passwords against your external database. So, I assume you have also implemented CredentialInputValidator interface. If you have not implemented CredentialInputUpdater, I would assume what you are trying to achieve should work out of the box.
If you have implemented CredentialInputUpdater, you could try to do the following:
Within you implementation of CredentialInputValidator.isvalid first check if the user has a local password configured, e.g. like this
keycloakSession.userCredentialManager().isConfiguredLocally(realm, user, credentialInput.getType())
If this is the case (returns true), simply have isValid return false. In this case Keycloak should use other CredentialInputValidators and check for the locally configured password.
If this is not the case (returns false), do the password check against your external database. Iff the password is valid, silently migrate the password to Keycloak's local credential store. This could look something similar to this:
CredentialProvider passwordProvider = keycloakSession.getProvider(CredentialProvider.class, PasswordCredentialProviderFactory.PROVIDER_ID);
if (passwordProvider instanceof CredentialInputUpdater) {
((CredentialInputUpdater) passwordProvider).updateCredential(realm, user, credentialInput);
}
Within CredentialInputUpdater.updateCredential make sure to update the local store in addition to the password in your database.
Now your user's passwords will be stored in Keycloak's local database / credential store and the built in password reset functionality should work as expected.
Is there a possibility to register a passward in keycloak for the user
just after the user is created in external database and then federated
to keycloak?
From the Keycloak Documentation itself:
By default, Keycloak will import users from LDAP into the local
Keycloak user database. This copy of the user is either synchronized
on demand, or through a periodic background task. The single exception
to this is the synchronization of passwords. Passwords are never
imported. Their validation is always delegated to the LDAP server. The
benefits of this approach is that all Keycloak features will work as
any extra per-user data that is needed can be stored locally. The
downside of this approach is that each time that a specific user is
queried for the first time, a corresponding Keycloak database insert
is performed.

Can Keycloak provide alternative authentication if LDAP is down

Let's say I want to have keycloak synced with the LDAP and use it as the source for authentication. (I've managed to do this already)
But is there a way to let the keycloak be itself the identity provider if, for some reason, the LDAP connection is down?
First you should avoid ldap going down, by setting HA, using HAproxy and keepalived for example, as for Keycloak, you can disable "Sync Registrations" in your keycloak LDAP IDP, and create users using the admin interface, these users are stored in your local database of keycloak, and not on the LDAP so even if its goes down those users can stil get access to Keyclaok.
Refer to https://www.janua.fr/understanding-keycloak-user-federation/ for more details.
I managed to create a custom LDAP Storage Provider to do this.
check How to create a custom UserStorageSPI on Keycloak

Use keycloak as auth service or IDP?

So, im doing research to know if its a good alternative to implement keycloak on the environment i'm working at.
Im using LDAP to manage users at my workingplace. I was wondering if is there a way to use keycloak as auth service in all upcoming systems and some of the existing ones. We are currently managing it with an IDP that we need to improve or replace, also there are some systems use their own login (this will eventually change).
The main problem i've crossed is that keycloak synchronizes against ldap and i dont want user data to be stored on keycloak, maybe if its only login data. User data is planned to be kept only on ldap's database in case that any userdata needs to be updated.
So is there a way to use keycloak only as an auth service fetching user credentials from ldap on every auth request?
pd: maybe i am mistaken on the meaning of what's an auth service an whats an IDP.
Actually it is not necessary that LDAP users are synced to Keycloak.
Keycloak supports both options
Importing and optionally syncing users from LDAP to Keycloak
or
Always getting the User info from LDAP directly.
But keycloak will always generate some basic federated user in it's database (e.g. for keeping up a session when using OpenID Connect - but you should not really care about that).
As far as I know (but I've not used that myself) you could also use keycloak to maintain the LDAP users data and write changes back to LDAP (see "Edit Mode" in Keycloak documentation)
Check Keycloak documentation regarding LDAP stuff to get more information https://www.keycloak.org/docs/6.0/server_admin/#_ldap
Beside the User-Data Topic, Keycloak provides a lot of different Protocols (like SAML and OpenIDConnect) to provide authentication for your services. So you could use different/multiple authentication protocols depending on your applications with just one "LDAP-Backend"

OpenAM + two LDAP servers

I'm a newbie in the LDAP + Liferay + OpenAM world, so I wonder if someone could point me in the right direction in a problem I have. In a real life environment, there are 2 LDAP servers, a OpenAM server and a Liferay application. What the customer needs is to authenticate users in Liferay against OpenAM, and OpenAM should use the LDAP servers. Problem is, the user exists only in one of the LDAP servers (it will be moved from one to the other in one point of the future). What the customer wants is:
Users must be able to authenticate independently of what LDAP contains the user.
The obtained token must be valid for both LDAP servers, as it will be used in a different service (I have no control over it) against only one of them to validate authentication.
As I said, I'm new to this world so, if the answer is too complex (I'm afraid it will be for me), maybe you could point me to books or docs that could resolve this scenario.
Thanks
You should configure LifeRay to use OpenAM for all authentications and you can configure OpenAM to use both LDAP servers (use different realms).
Details for OpenAM configuration will be in the OpenAM documentation.
As the previous answer states you should route all your authentication requests to the OpenAM server and let it validate the credentials against the right LDAP server. Using two different realms (one for each LDAP server) won't work in your case since that will require LifeRay to know where to find the user before hand. Also, sessions are linked to a specific realm.
There are multiple solutions to your problem. Here are just a couple:
Option 1
If you have control over the authentication flow. That is, if your application uses a custom UI and communicates with OpenAM via REST, you could create two different authentication module instances under a single realm (let's say two instances of the DataStore authentication module) each one pointing to a different LDAP server.
Let's call this module instances DataStore1 and DataStore2. Your application can collect the user credentials (username and password) and submit them to DataStore1. If authentication succeeds the user is already logged in. If it fails, the application can try with DataStore2.
Of course this is not ideal since you'll be making two authentication requests per login instead of just one.
Option 2
A better option (though more complicated to implement) would be creating a custom authentication module. This module can try authenticating the user against LDAP Server 1 and then try with LDAP Server 2 if the first authentication failed. Notice that with this option you don't need custom logic on the application side since it will only send a single authentication request to the OpenAM server. In fact, you can protect your application with an OpenAM Policy Agent.
Another advantage of this approach over Option 1 is that you can migrate your users behind the scenes assuming that the end goal is to migrate users from LDAP Server 1 to LDAP Server 2. If the first authentication succeeds your custom code could read the user entry from LDAP Server 1 and copy it over to LDAP Server 2.
Hope this helps you solve the problem.

How to configure LDAP authentication module instance in OpenAM

I am trying to protect a Java servlet with OpenAM + J2EE tomcat agent. I got this part working by using embedded OpenDJ of OpenAM.
Now I am trying to authenticate against a LDAP server, so I added a LDAP module instance for OpenAM, but I get "User has no profile in this organization" when I am trying use uid/password of an user from that LDAP store.
I checked OpenAM administration guide on this the description is rather brief. I am wondering if it is even possible to do this without using the data store configured for OpenAM?
The login process in OpenAM is made of two stages:
Verifying credentials based on the authentication chain and individual authentication module configurations
User profile lookup
By configuring the LDAP authentication module you took care of the authentication part, however the profile lookup fails as you haven't configured the user data store (see data stores tab). Having a configured data store allows you to potentially expose additional user details across your deployment (e.g. include user attributes in SAML assertions or map them to HTTP headers with the agent), so in most of the scenarios having a data store configured is necessary.
In case you still don't want to configure a data store, then you can prevent the user profile lookup failure by going to Access Control -> <realm> -> Authentication -> All Core Settings -> User Profile Mode and set it to Ignore.
This is unrelated to authentication but it's related to authorization ... you have to configure appropriate policies ... see OpenAM docs.
Agents will enforce authorization, OpenAM determines if the user has the permission to access a protected resource.
As Bernhard has indicated authentication is only part of the process of granting access to a user. He is referring to using a Policy to control access.
Another method is to check if the authenticated user is a member of the desired group programmatically. This can be useful when you want access control over resources that OpenAM doesn't know about (e.g. specific data).
For example, lets say that you want different groups to have access to different rows in a table in a database. You can retrieve the group information associated with the user and add that to your database query, thus restricting the data returned.
I'm sure that you could do this with OpenAM as well using custom modules to allow the policy to use information in the database as resource, but I've found it is much simpler to perform this fine grained access control in your code, and is in all likelihood significantly faster.