Sharing a session between 2 different clients of the same realm

hi,
I am working on SSO with keycloak and openid.
I have two clients 1. angular app(client1) 2. kibana(client2). My use case I just want to login to angular app(client1) and client 2 will login with out asking for credentials. and it is working fine. but when I call api’s of client2 inside client1, I am getting authorization error. I don’t want to pass user credentials again in headers to make api call.

Some more details regarding my use case:
- 2 clients connected to the same Keycloak realm (via openid)
- user logs in to 1st client and opens a webpage that makes a REST API calls to 2nd client.

is it possible to make rest calls to client2 with out passing credentials in header as sso is working. if so, please give suggestions.

thanks in advance

Each web application/api accepts only tokens from used client usually. That’s secure. Of course some apps/libs may accept also tokens from another clients/IDPs, but it must be configured explicitly in their configuration.

API needs credentials in header usually. API calls are in the background (AJAX/axios calls), so for them SSO doesn’t work - you won’t be able to see any login screen in the browser.

Typical use case for SPA (Angular, Vue, React, …): frontend part obtains token and manages token validity (e.g. token refresh). Then you will have “guard” in the frontend, which injects token to each API call automatically.
Backend (API) doesn’t handle any redirection to Keycloak login. It just verify token - authentication, maybe authorization and it will process request or deny request with correct status code.

hi @jangaraj
thank you for reply,

when I login to client1 is it possible to get authentication cookies of client2.
case1:(working fine)
when I login to angular app (client 1) it will ask for credentials and when I load/open Kibana(client2) it will give two cookies(security_storage, security_authentication) with out asking for credentials as SSO is working fine and api (client2 api calling from client1) is also working with out credentials as I have cookies.
case2: (my use case)
I don’t want to open Kibana(client2) page. how can I get cookies with out loading client2, basically I am searching for Api(calling from angular to keycloak) where I can get authentication cookies of client2 with out passing credentials as I already logged in to angular application.

Hi @ravindra

Can you clarify if you have control over the client2 api and make it accept an access token from client 1?

Also, look into the notion of audience that tells the ressource server (client2 api) that the token is also for it.

Another more complex alternative is to have client1 perform a token exchange for a client2 token. It can be done with keycloak but it is not a strait forward config. Client1 will then get a token for client2 api.

Another aspect is that you talk about cookies in your app. These cookies contains the access tokens or are a session id that allow the back end to get the access token? Are the api servers able to get the access tokens from the cookies rather that the authorisation header?

hi @guenoledc,
thanks for your reply

I did token exchange approach as you said,

*working fine:(in postman)

I called token exchange post api of keyclaok (https:/localhost:8443/auth/realms/myrealm/protocol/openid-connect/token)
and i am passing following in body as x-www-form-urlencoded

  • client_id
  • client_secret
  • grant_type
  • subject_token --(is access token came when I login to client1)
  • requested_token_type
  • audience
    and I am getting response with exchange access tokens. and when i pass access token in response to authorization header to my client2 api i am getting setcookie headers. which i want.

not working:(when calling token exchange api from angular )

when i call openid-connect/token api endpont in angular iam getting invalid token error, though same token when i check in postman i am getting result.

this is how my api looks:

getexchangetoken(){
var token = sessionStorage.getItem(“access_token”);
const body = new HttpParams()
.append(“client_id”, “aiopsclient”)
.append(“client_secret”, “3e34f688-1c98-48c6-8fc5-978f96af5390”)
.append(“grant_type”, “urn:ietf:params:oauth:grant-type:token-exchange”)
.append(“subject_token”, token)
.append(“requested_token_type”, “urn:ietf:params:oauth:token-type:refresh_token”)
.append(“audience”, “kibana_sso”);
this.http
.post(this.openidurl,body,{
headers: new HttpHeaders({
‘Access-Control-Allow-Origin’: ‘*’,
‘Content-Type’: ‘application/x-www-form-urlencoded’
}),
})
.subscribe((data) => {
return data;
});

is this the correct way of sending parameters in angular?

thanks in advance

Hi,
you have to send authentication request from your client2 to keycloak. Keycloak will not display the login form as end-user is already authenticated using client1.

To resume, client1 and client2 implementation in regard to authentication should be same and keycloak will manage sso behind the scene for you using sso cookies. It’s not not the responsibility of clients to manage sso