Configuring Cookie Domain of Keycloak Cookies

Hi

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.

Hi @jangaraj

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.

Thanks for your reply and help @jangaraj

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.

But the important part is, that drive.google.com does not redirect all users to accounts.google.com. Only if you click Login or you have an active session on the IDP, it redirects you to accounts.google.com.

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.

Hi @zonaut

That’s what I’m doing. But then application 1 looks like the user is not logged in even though the user just logged in on application 2.

Just checked the source code. The domain is always set to null and therefore the full qualified subdomain is being used.

1 Like

After thinking about this I may have a similar case or problem which I didn’t look into yet.

eg. I have 3 domains

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.

For people who are interested can check the following https://github.com/keycloak/keycloak-documentation/blob/master/securing_apps/topics/oidc/javascript-adapter.adoc

Quick and dirty example

<script src="https://id.domain.com/auth/js/keycloak.js" type="text/javascript"></script>
<script>
    const keycloak = Keycloak({
        "realm": "realm-name",
        "url": "https://id.domain.com/auth",
        "clientId": "public-client-name"
    });

    keycloak.init({onLoad: 'check-sso'}).then(function(authenticated) {
        console.log(authenticated ? 'authenticated' : 'not authenticated');
    }).catch(function() {
        console.log('failed to initialize');
    });
</script>
1 Like

@zonaut

That’s exactly what I was looking for. Thanks a lot!

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?

Hi @artemana

The JavaScript Adapter by default sends the access token in the Authorization header. You should just use that in your backend.

In my case I switched from a stateful backend to a stateless backend because I don’t have to store the tokens in the HTTP session anymore.

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 :slight_smile:

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 :slight_smile:

Hey @thomastardy, could you please share a link to that piece of code? Thank you!