How can I create a new social User on KeyCloak via REST APIs? - keycloak

I have a working KeyCloak installation, and a Laravel backend that uses this to authenticate Users.
The KeyCloack server is already configured with some external ("social") identity providers.
Now I want to create, from PHP backend, new "social" Users on KeyCloak via REST API before they attempt to login the first time.
My goal is to create new Users on backend database with their all profile data, in order to have all the user set-up already done once the user will first login on my app.
Is there a way to do this?
Have I to create the user firsty on KeyCloak and then link it to a social provider in some way?
Or something other?
Thanks

There are essentially two steps required:
You have to create a login-flow, that maps the SAML-User to the local user.
This must contain the "Detect Existing Broker User" and the "Automatically Set Existing User" Execution as Required.
Your Identity Providermust use this as login flow.
Then you have to configure your SAML Identity-Provider to identify the SANL-Atrribute to match the user. Feal free to ask if you need further help for this.

Related

Keycloak - allow linking of 2 accounts with different emails

I need to implement a login flow with KeyCloak where a user will be prompted to reauthenticate with an existing account (by email/password or via social IdP) after authentication with a non-existing social  account OR choose to create a new KeyCloak account.
Something like on the picture below:
Is it possible to implement such a flow with KeyCloak?
It is possible that flow with regular Identity Providers feature in Keycloak
Overview Steps
detail information here
1. IDP URL
{keyclaok URL}/realms/{realm}/broker/{idp name}/endpoint
example:
http://localhost:8180/auth/realms/test/broker/stackoverflow/endpoint
2. Register Application at Social App
example: StackOverflow https://stackapps.com/
3. Get Client Information from Social App
example: StackOverflow
4. Set IDP at Keycloak
5. Test
5.1 Before add user
5.2 login by Social
5.3 Update user account (set password and e-mail)
5.4 check added user
5.5 Test added user login by username/password OR
Social Icon Click without credential
5.6 logged in test by both ways
5.7 Picked up e-mail from Facebook and detect e-mail already exists.
5.8 I select "Add to existing account" then filled out e-mail and password from Keycloak.
The authentication flows within Keycloak can be customized (virtually all of the flows can be customized or extended). I believe you'll need to implement a custom Authentication SPI (Service Provider Interface). This will be a JAR that you can add custom logic upon account creation.
Here's the Keycloak documentation for SPIs.

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

If I used Ejabberd authentication with JWT, I don't to need to register the user?

Currently, I have a social media project that already has the existing users, I want to enable the chat function. I had config Ejabberd with JWT and Mysql. I tested and I realized that I don't have to register the users in order to chat, I just need to make sure my token has "JID". Is it a good approach? Or do you have any other suggestions?
You don't need to register the users to ejabberd server explicitly while using external authentication mechanism.
However, chances are that you might not be able to see the list of registered users on the admin panel when not using the default authentication mechanism.

How to create a user from a id_token with Spring?

I am building a SPA with a spring on the backend. I am working on signing in with Google, most of it is working already: got the id_token with the implicit flow in the frontend and I sent it and verified it on the backend.
I want to have users with roles and manage that locally (so, no adding info in the oidc provider). What are the options to go from the id_token to having an authenticated user in spring? I did not find any example doing that link manually (id_token-spring_sec_user).
I have checked several sources like the Spring Security 5 presentation at SpringOne https://www.youtube.com/watch?v=WhrOCurxFWU, several SO questions and posts on okta's and auth0's blogs but I am still missing the link.
You will have to create your own (application) specific roles.
Use these steps :
Get authenticated from Google
Access the profile section from google (username, name etc )
Use your own user table to store this info
Create admin APIs in your own system and assign your app-specific roles to the user.
When you login again you will authenticate against google login/password and roles specific to your application .
Create an account or session with the id_token
Check if the user is already in your user database. If so, establish an authenticated session for the user. If the user isn't yet in your user database, create a new user record with default role from the information in the ID token payload, and establish a session for the user. You can prompt the user for any additional profile information you require when you detect a newly created user in your app.

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.