Is there a way to configure the cookie domain keycloak uses when creating the cookies?
I would like to set it to the domain and not the sub-domain keycloak is using. The idea is, that application 1 using another sub-domain can read the keycloak cookie and can figure out, that the user already signed in (probably using application 2) and therefore can start the OIDC authentication flow without the user seeing a login form.
Basically, I want to have the users authenticated in application 1 immediately when and only when they authenticated before using another application.
Your help is very much appreciated.
Thanks and Regards
Why are you using 2 different sub-domains for the same Keycloak?
It looks like you are using 2 different IDPs from the OIDC perspective now. You should to use the same domain everywhere and SSO will be working as you are expecting.
No, Iām not using 2 different sub-domains for keycloak.
I have 1 subdomain for keycloak, one for the application 1 and one for the application 2. What I want to achieve is that application 1 can figure out based on the keycloak cookie, that the user has an active session without redirecting the user to the OIDC flow. I want to do that by reading keycloakās cookies. And if the user has an active keycloak session, only then will I redirect the user automatically.
In order to access keycloakās cookies from the sub-domain of application 1, keycloak need to set domain cookies and not subdomain cookies.
What is ākeycloak cookieā? For me it is IDP sessions and that one is related to Keycloak domain, not to the app domain. Generally, use grant code/implicit/PKCE flow in your app so login will be done on the Keycloak domain and you should to be fine.
You need to redirect user to OIDC login from the app always. But opened IDP session (cookie on the Keycloak domain) makes that no user credentials will be needed and token will be issued to the app immediately - just a few redirects in the browser, which you as an user wonāt be able to notice - that is single sign on.
Of course if you are using Direct Access Grants flow (maybe another obsucure login procedure) directly from the app, then you donāt have IDP session.
Keycloak uses a cookie to identify the users session.
What I want to achieve is what google is doing with e.g. mail.google.com and drive.google.com. You can access both sites without being logged in. In these cases, it shows you publicly available content. Then you log in on e.g. mail.coogle.com. When you den go to drive.google.com you are immediately logged in. Googleās IDP (accounts.google.com) uses the domain .google.com when setting cookies, not the subdomain accounts.google.com. Therefore, all applications running on *.google.com can read the accounts.google.com cookie and can figure out, that the user has an active session. In this case, it redirects you to the IDP on accounts.google.com and you are logged in.
I want to implement the same behavior in my applications. But in order to do that, I need keycloak to store itās cookies not on the subdomain keycloak.mycompany.com. It needs to use the domain .mycompany.com.
Therefor my initial question, is there a way to configure the cookie domain keycloak uses when creating the cookies?
You donāt need to read the cookie for your purpose.
You canāt also rely on a cookie to give you an accurate value on that point in time, Keycloak is your single truth.
Just exclude paths in you sub domain app that you donāt want to have secured.
So in the case of the app domain I donāt have any problem, I need to be logged in so problem solved.
But in the case of the www domain I will need to have some pages secured which is not really a problem because when the user visits those pages he will be redirected to Keycloak, login and will be redirect back with access to it.
But here is my problem, I want to know if the user is logged in on the public pages so I can show a button with login or drop down with logout. Especially when switching between app and www.
This is probably the same problem that you have?
How can I check this?
Can I have some Javascript in the background which checks this?
Iām testing something with onLoad: ācheck-ssoā at the moment, will update this.
UPDATE
So stupid me, being out of Keycloak for a while I forgot I can check this with the ācheck-ssoā option. This way Iām not redirect to Keycloak but can check if Iām logged in from Javascript in a static page.
Sorry, I am bit confused now. The check-sso option will simply flag you at the browser whether user is logged in or not. But how about server side? In my case Iām having servlet filter there. How will that part be able to trust the requests if cookie domain is not set?
Butā¦ you cannot send authorization header when user clicks on a link, right? Following that approach I need to hook up every single a element and emulate naviation with javascript. Then, also direct navigation to https://www.domain.com/secure/page would be missing that header as well as page refresh, etc. I mean there seem to be no way to avoid server side authentication layer to provide good user experience.
And then Iām hitting to the challenge in the first message of this conversation: KC cookies are set to app.domain,com, not to www.domain,com
Well, seems I do need to try it. Feels like Iāll be back
KC cookie is set on the id.domain.com domain. I think you need check some flows on how OpenId Connect works. There is a reason why you need to set a valid redirect url and web origins in the client you create in Keycloak, that way it knows which urls are allowed. The state of your login is on the id.domain.com
Why do you think you need to set a header when clicking a link? The javascript adapter is just there to check if we have access, renew token, etcā¦ Read up on the link I posted on the Javascript adapter.
When you are doing a call from javascript to an API for example you need to set the Authorization header with the token you retrieve from the javascript adapter like the app.domain.com in this case.
The API will intercept the token and validate it against Keycloak to see if you can access a resource.
The www.domain.com is a Spring Boot Thymeleaf example in this case.
On non secured pages I just use the javascript adapter to check if Iām logged in so I can manipulate the html to show a login button or logout button.
On secured pages on www.domain.com I use Spring boot to check if I have access to that route so I can map it to a user in my own db and use that data on my secured pages.
But my secured pages could have been just html and javascript or Angular or whatever javascript framework and I would check if my token allows me access to a route and do calls to an api with the authorization header.
The secured page doesnāt need a header, a refresh on that page will just invoke javascript to check if I have access and thatās it.
I donāt know if that cleared it up somehow?
This is a good resource by the way on these topics https://www.oauth.com/
Thank you for helping, guys. Like @thomastardy I also went into pure browser based authentication mechanism. Making both server side (servlet filter) with some āsecureā pages ended up to be a nightmare in my case.
So, what seems to work is:
server side checks if a āstatusā cookie is present
if yes - serve what was requested
if no - serve a āloaderā page which does ācheck-ssoā, sets the cookie and reloads page
and then whatever page needs user authentication: ālogin-requiredā happens
Why so complex stuff - I have SPA for authenticated users and plain web pages for anonymous. So, wanted to have same urls for these two groups of users (to allow url copy-pasting to work)
What adds complexity. In addition to id.domain,com, i have potentially thousands of user domains like site1.domain,com, site2.domain,com, etc So, having an own kc client created for each of these subdomains. With servlet filter Iād need to keep client secrets for each of domains. Which is sort of doable, but is quite ugly
IMHO, the ācheck SSOā strategy is not an optimized solution for this use case. It actually redirect the user to the IDP with āprompt=noneā. And this is not necessary if it is possible to know in advance that the user is not yet signed in.
An option , could be to set a custom cookie at the .domain.com . This cookie will just indicate to the applications within this domain and its sub-domain, that someone has signed in and may be still connected.
Applications can then perform a ācheck SSOā only in this case.
The issue is to manage this cookie within a keycloak extension so that its lifecycle mimics the KEYCLOAK_SESSION cookie (i.e. set when the user successfully signs in and unset when he is login out).
If someone has already implemented such extension and is ok to share some tricks , heāll make my day