Provide "Forgot Password" feature in Keycloak to certain users only - keycloak

We're using Keycloak 12 for authentication in our portal and there are two different types of users:
Internal users (read from our internal LDAP)
External users (stored in Keycloak but without being synced with the LDAP)
We'd now like to use the "Forget Password" feature provided by Keycloak. After having configured the feature and the mail server, this works fine out-of-the-box.
However we'd like to restrict the "Forget Password" feature to all users which belong to (2), i.e. the internal users. These users are not allowed updating their password via Keycloak as this is done by another mechanism.
I couldn't find any information in the documentation so far if this is possible at all?

The Keycloak Forgot Password feature is applied at the Realm level, hence applied to all the users belonging to the Realm. For Keycloak, the LDAP is just an external storage with users to authenticate against. Consequently, out of the box, there is no way (as far as I know) for the Forgot Password to only be enabled to certain users within the Realm.
Even if it would be possible IMO it would not be a very user-friendly feature, since when one activates such a feature a new link will be shown to the users on the login page in case they have forgotten their passwords. So if a user from the LDAP would click on it, it would display an error or something?!
Alternatively, you can configure the LDAP of the so-called internal users in another Realm than the one with the Forgot Password enabled. And then configure the newly created realm to be an external Identity Provider, which the users could explicitly authenticate against it. So in practice, the users would lend in the normal login page, the external users could login normally, and would have the Forgot Password option enabled. The internal users would explicitly click on the external IDP to authenticate themselves. Log in using the external IDP would be a similar user-experience as log in to the normal login page, however, the Forgot Password option would not be shown.
You can see an example such configuration here.

Related

Keycloak: How to log in to another Keycloak instance's realm without redirecting?

We have two Keycloak instances:
Keycloak-A: publicly available
Keycloak-B: available behind a VPN
Both instances can communicate with each other directly without any restrictions.
Is it possible to log in as a user from Keycloak-B using the login form from the public Keycloak-A?By adding Keycloak-B as an IDP on Keycloak-A the login request gets redirected to Keycloak-B.
Exporting the realm from Keycloak-B to Keycloak-A is not an option.
Is it possible to log in using Keycloak-B users without getting redirected on Keycloak-A?
Keycloak allows to set up different User Storages to retrieve user credentials. This is called User Storage Federation. Out of the box Keycloak supports LDAP / Active Directory. If your Keycloak-B already retrieves its user information from some other source like LDAP or AD, it would be easiest to establish a secure connection between Keycloak-A and this other source, too.
If your organisation directly uses Keycloak-B's H2 database to keep all user credentials and for some reason doesn't want to set up an LDAP or similar, I only see the possibility that you try to implement your own custom User Storage SPI for Keycloak-A to retrieve this user data from Keycloak-B.

Flask-OIDC | How to call a specific function after the user logged in

I built a login system using Flask OIDC and Keycloak. In my system, there is some endpoints decorated with oidc.require_login() that calls the Keycloak login page.
My goal is, after the user successfully logged in, my system checks if the user name exists in a specific database.
How can I set a function to be called every time someone successfully logged in with Keycloak and do this verification at the database?
According to your needs there are several ways to create the user in the backend.
The easiest way would be to just check the JWT token on every request. OIDC is based on JWT and that token is available on any request (which should already be done to find user roles etc). So your application can check that JWT and extract the username from it (see here for details about the JWT format). With the username you can check your internal database and create the user, if it doesnt exist. But at that time you'll not have access to any user credentials any more. It is just SSO and you need to trust Keycloak and the JWT... Also - you'll never be informed, if the user will be deleted in Keycloak, which could be an issue.
There is a callback API in Keycloak in form of the Admin URL per client. But the documentation is not clear. It says: It’s used by the Keycloak server to send backend requests to the application for various tasks, like logout users or push revocation policies. But I cannot find a complete list of "tasks". I saw only logout events. see Keycloak documentation and the documentation only talks about that. If I add an admin url to a test client, I did not get any requests at login time.
a different but more complicated way would be to create your own UserStorage SPI in Keycloak. It would be Java of course, but only some classes. There is an HTTP example or have a look at the LDAP user storage SPI, which supports registration too. If you choose that for your realm and a user tries to login to Keycloak (Login form), the SPI can call your backend to check the user. It also could be "used" to create the user in the backend by checking the Keycloak local storage and only if there is a local Keycloak user, call the backend. That isn't the reason, why you should implement the UserStorage SPI, but it's possible. If you think, this is a good idea, I would prefer to use your backend storage as the one and only storage or build a different one, that then could call your real backend in case of a new user. I would use this one by not using Keycloak local stored users but, by using your own database.
next (maybe last one). You can write an EventListener SPI to read all events and only filter the login events, see here and here. I think, that would be the easiest one. But be aware. In that case, the HTTP call to your backend coming from the event itself is based on a normal HTTP request (without OIDC at that time).
The last two examples create a JAR (which is explained in the links). That JAR with the SPI must be deployed in keycloaks standalone/deployments folder. The EventListener should be active by default, the UserStorage SPI must be activated per realm.
But - be aware - Keycloak/SSO/JWT - should not be used by creating users in multiple backends. Syncing the users between all backends in a SSO environment is maybe the wrong way. Most information is located in the JWT or can be called by a backend from one central user identity management. Do not store a user more then once. If you need the user reference in your backend - link just to the username or userid (string) instead of a complete entity.
There is no direct way of doing this, other sotfware like Openam, Okta allow you to trigger specific flows in a post-login configuration.
In keycloak, you can try to create your custom authn flow(using Default Identity Provider, its the only option that allow a redirect), and then select this flow in your Identity provider in post login flow.
The idea here is that after login, the user will be redirected to a link ( an api call that will verify his presence on the external database, and sent him back to keycloak once the verification is done.
More info here

Authorization new user - keycloak

I want to secure my user registration page with keycloak but couldn't think of any approaches while reading the docs. The best option for me:
New user register, but his account is unavailable.
When ADMIN accept this new account, user can log in.
Is it possible do it in keycloak ? Or any similar solution ?
Sure you can do it. The easiest way is to give a default role to newly registred users. The default role would give only minimal privileges. Then ADMIN can promote the user to the more appropriate group or role.
Probably to "automate" or smoothen the second part of this flow you might need some flow customization. Cf. https://www.keycloak.org/docs/latest/server_development/#required-action-walkthrough and related.
Another solution is to give to the default minimal role the possibility to request acceptation, or make the request automatically at first logging (eg. mail sent to ADMIN).
EDIT
Programmatically it is also possible to make calls to the Keycloak Admin API (through native Admin Client). For example, you can write some logic (and associated UI or whatever) that will assign or remove groups from a user.
See. Admin REST API

Keycloak flow to allow only authorized IDP accounts

I would like to setup Google federation using Keycloak however only for authorized users in my company.
Setting up Google federation allows any Google account to login.
I have looked at the authentication flow on Keycloak but I have been unable to find a way to set it up. I can think of a few simple scenarios that I had hoped Keycloak allowed out of the box
Instead of automatically creating an account when somebody tries to login, require that an account with the exact same email/username already exists and just link them based on the email when that specific user tries to login.
Automatically create an account the first time the user logs in using Google, link them however require an admin to manually activate the account before it can be used
A combination of the first 2. Enable registration, allow the user to register an account and require an admin to activate the account, at which point the user can link them.
Try as I might, I seem to be unable to configure this. There seems to be no way to have Keycloak create an account that requires activation and if I try to create a flow where the "unique account creation" authenticator is not include, it immediately throws the user to an "invalid username/password" screen.
Did I miss something? Is there no other option than manually creating an account and linking it for every single user (or write my own authenticator which I am trying to avoid)?
If you are OK with folks from a single domain (e.g. #yourco.com), you can use the Hosted Domain parameter on the settings page. For google specifically, at least as of keycloak 11.x, both google and keycloak will ensure the user's email address matches the entered domain. I do not know if it's possible to enter multiple domains.
What we do is use the hosted domain option, and grant these new users a simple role that allows them to log into the admin panel and have read permissions on a few simple areas. This makes it easy to setup new accounts in Keycloak, we just tell users to go log in and they are setup with basic access. If someone warrants more advanced access to read private data or even write some data, they have to contact our ops team who may choose to grant them some more roles in keycloak
You could implement a custom form action. It's easier than you would expect.
If you don't want to write code you could maybe use the 'script' form action which is already available. You can get to it this way:
Authentication -> Select 'First broker login' in the dropdown -> Make a copy of it (Making a copy of it allows you to edit it). Now click 'Add execution' and chose 'Script'. Move it upwards to the top, so it's the first form action in your flow. Put the radio button on 'REQUIRED' and go to actions -> config. Now in the script you could check the username or email to match a pattern (maybe the domain name of your company), if the pattern match fails, you can call the context.failure(..) method, which is already available in the default script.
Make sure that you select this (new) first broker login in your identity provider configuration.

How to setup initial user/role enabling SAML SSO

We are a service provider. Suppose in our application, we originally have our own user/role management. Different users with different roles are allowed to use different features. So that when a user login we need to know which roles this user has, and prepare appropriate UI. We have administrator role, users with this role can assign roles to other users.
We are thinking of enabling SAML SSO for our application, now the problem is how do we setup roles for each user.
Solution 1, we relies on IdP to provide role information for each login user, the role information may come along with Assertion, but this may not work for all the IdPs.
Solution 2, we only retrieve user from the IdP, and manage the roles in our own application. For example, when we get an Assertion, we retrieve the username(or email address), and match with a record in our DB, if it doesn't exist we automatically create one for this new user. Then we rely on users with administrator role to assign correct role for this new user.
Now the questions is where is the first administrator coming from? Our customer gets our application, and turns on SAML SSO, now there is no users in the DB yet, then how can we resolve such bootstrapping issue? Is there any kinds of standard way? We have come up with different options but not sure which is better and what are the concerns for each options.
Option 1, have a default built-in administrator user. There is a regular native login page that built-in users can login without going through IdP(there is an option to turn it on/off if SAML SSO is enabled)
Option 2, during SAML SSO setup, ask for the administrator user name, so that we automatically create this user in our DB with administrator role. Then when this user login through IdP we could match him in our DB.
What are the other options?
For your first question about who should handle the roles. As I understand every customer has your One of your service provider software. And it connects to a central IDP that you own. If this is the case, it feels like its to complex letting the administrators handle roles on your IDP. I would go for number two.
About question number two. I have been in the same situation I can not remember that I have seen a obvious standard solution for this.
What we did was option 2. It works fine but it adds some complexity to the install procedure. We choose it because we would not have a native login page.
I thing maybe I would be better to go with option 1.
You can get the roles from the different directories of your IDP using your authorization layer. It removes the constraints on SAML and gives the same results as your solution 1.