Unique login for multiple clients in KeyCloak - keycloak

In Keycloak, is it possible to have only one login for all the clients in the same realms? I have configured the server (from the admin console) in this way:
- create a new realm (let's call MyRealm);
- create two different clients (Client1 and Client2)
- create a user (Alice)
I have tested the two clients individually, and they works fine (the default keycloak login page appear and if I provide the credentials the browser redirects me correctly); the problem is that when I am logged in in Client1, and go (from the same browser) to Client2 the login page re-appers. Is it possible to configure the server in a way that I have to log in only with one client, and then I am authenticated also in all other Realm's clients? Thanks.

I solved this problem configuring only one client (named UniqueClient) from Keycloak admin console; then I modified the two java applications (Client1 and Client2) and now all of them are pointing to UniqueClient (in their keycloak.json there is 'clientId': 'UniqueClient'): in this way when I start one of them the keycloak login page appears, and if I log in, I'm logged in also for the other application (unitil the session expires);

You can achieve this by using https://github.com/IdentityModel/oidc-client-js/wiki so you will be logged in several clients at the same time on the same realm

Related

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

How to disable the SSO feature in the Keycloak

I want to use Keycloak as an identity provider in our company.
I have defined one Realm with three clients (I have three applications and I have defined a client for each application)
I want to separate the process of login and logout for each application. For example when I login into app1 and app2 and app3, and then logout from app1, the app2 and app3 remain logged in.
In StackOverflow I found some solution to separate the login process for each application as follow:
1. in admin console, go to Authentication
2. make a copy of Browser flow
3. in this new flow, disable or delete Cookie
4. go to Clients -> (your client) -> Authentication Flow Overrides, change Browser Flow to your new flow, click Save."
How to force login per client with keycloak (¿best practice?)
But this solution is not working for making the logout process independent for each application(which means I want to disable the SSO feature in Keycloak). Is there any way to make it possible?
I would enable Direct Access Grants on the client level only (Standard Flow will be disabled), so applications will have to use direct grant flow. No IdP sessions in the user browser will be created in this case, so no SSO will be used.

Keycloak : Single Logout(SLO)

I am using Keycloak as the OP of a single sign-on(SSO) platform. I already connected two of my web applications to Keycloak for the single sign on function to work.
Also, I have already made one app when logging out will be redirected to Keycloak authentication server. But I want my other app to also logout when the first one logs out(SLO function). What configurations do I have to do for my 2nd app to make this happen?
Thank you for your help =)
I managed to make the single logout to work, it seems that you just have to set the URL of your web app in the Admin URL(inside Keycloak command console, under Clients).

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.

Jasig CAS Single Sign Out - Logout

I'm currently making tests with the CAS server 3.5.2 and I'm facing
problems with the logout.
My knowledge in these topics is limited and I don't manage to go further on
that point.
I installed a CAS server and I've got 2 instances of the same java
application that point to that CAS server (appologize if I don't use the
adecuates terms).
So, when I access to the protected resources of my client aplication, I'm
redirected to the CAS login page, I check in my DB if credentials are ok
and then I access the resource. Then, if I access to the same protected
resource from the second instance of the client application I'm not
redirected to login page. That's perfect.
The problem is situated in the logout. To do so, I first execute a
session.invalidate() and access to the CAS logout page. It's ok because,
from the application from which I logged out, I must login again to access
the protected resources. On the other side, the second application remains
connected and I can access the protected resources without login again.
Well, I know that the session.invalidate() is local to the first
application but I thought that CAS server would have "broadcasted" the
desconnexion to the other application but no.
Is there somebody who can give me experience feedback for the single sing
out topic ?
First make sure that SSO is enabled in the CAS properties file, if not make sure the SSO Listener is enabled in the clients.
If they are enabled then my guess would be the issue is in either the LogoutManagerImpl.java or SamlCompliantLogoutMessageCreator.java files.
The SSO in CAS is performed through the back-channel by transmitting a SAML XML message.
I had an issue with the SSO function last year only to find out that the XML message being broadcasted had an error that prevented it from being parsed.
Finally I solved...
In web.xml, the order of filters is important. Filters for Single-sign out must be placed at the begining.
See that section https://wiki.jasig.org/display/CASC/CAS+Client+for+Java+3.1#CASClientforJava3.1-OrderofRequiredFilters