Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 538
yasko Avatar asked Jun 16 '17 07:06

yasko


2 Answers

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...

like image 53
Peter V. Mørch Avatar answered Oct 19 '22 10:10

Peter V. Mørch


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.

like image 23
Michał Łazowik Avatar answered Oct 19 '22 11:10

Michał Łazowik