Getting UserSessionNotes returns null, while data persist

Hello, Keycloak users and devs!
I am confused with UserSessionNotes behavior, and will be very glad to take feedback.

Keycloak 11.0.2

I would like to use UserSessionNotes to share data between authentications performed inside one SSO session. I use custom Authenticator to set and get UserSessionNotes. Also I have User Session Note mapper for populating claims using UserSessionNote data.

I set UserSessionNote value in first Authentication session, but always found clear UserSessionNotes in any next Authentications sessions, wherein UserSessionNote mapper successfully continues map “invisible” for Authenticator UserSessionNote data to claims in any consequence Authentications (performed in one SSO session).

Example, to be more clear

  1. Client_1 authenticates with creds (first SSO authentication):
  • custom Authenticator set some_value in UserSessionNotes
  • UserSessionNote mapper successfully map some_value to token claim
  1. Client_2 authenticates (or Client_1 second time): SSO works - no creds needed, cookie used:
  • custom Authenticator fetches UserSessionNotes and found them absolutely clear from any key-values
  • UserSessionNote mapper successfully map some_value to token claim!

Inside one Authentication session, Notes set / get working well.

I am using for Note setting:
context is AuthenticationFlowContext.
context.getAuthenticationSession().setUserSessionNote(name, value);

For getting:
context.getAuthenticationSession().getUserSessionNotes()

How should I fetch UserSessionNotes data which were set in previous Authentication sessions (of the same SSO)?
Are there another ways to store data having SSO session lifetime and accessible in Authenticator?

Found that I able to get right UserSessionNotes values via indirect way (through UserSessionModel). But initial question still actual.

Example (suits when only one SSO session / UserSessionModel exists at time:

List<UserSessionModel> userSessions = context.getSession().sessions().getUserSessions(context.getRealm(), context.getUser());

// Select UserSessionModel of the current SSO by some way (should be replaced with correct filter):
UserSessionModel userSession = userSessions.get(0);

Map<String,String> sessionNotes = userSession.getNotes();

There are two questions:

  1. Why context.getAuthenticationSession().getUserSessionNotes() returns empty Notes Map while UserSessionModel have to be already associated with AuthenticationSessionModel (in case of Cookie Auth flow completed with success)?

From docs:

“Cookie provider then executes. Its purpose is to see if there is an SSO cookie set. If there is one set, it is validated and the UserSessionModel is verified and associated with the AuthenticationSessionModel.”

  1. To use indirect way specified above I need to use some match criteria to filter List<UserSessionModel> and find one attached to current SSO. Which one should I use?

Hi,

Just some quick overview how it works:

  • When user first opens the browser and wants to authenticate, the first authentication Session (EG. authSession1) is created. This auth session is used for the whole time of authentication (during the time when user filling his credentials etc)
  • After user authenticates, the userSession (EG. userSession1) is created and notes from the authSession1 are set as the userSession notes (via. userSession.setNote)
  • When user wants to “authenticate” for the second time inside same browser, he is authenticated automatically due the SSO. But before he is authenticated, the completely new authSession (EG. authSession2) . But after successful authentication, there is still the same user session userSession1.

In other words, there is single userSession per whole browser, which is removed after user logouts. However there can be mulitple authentication sessions per browser and all of them tight to same user session.

So for your example, the “authSession2” won’t share any data (EG. authSession.setUserSessionNotes) set by the authSession1. However what you can do in your authenticator is to read the notes from userSession.getNotes . The userSession can be obtained in same/similar way how the CookieAuthenticator is doing for example. In other words, for subsequent SSO authentications, you need to use userSession.notes instead of authenticationSession.userSessionNotes.

2 Likes

Thanks a lot, @mposolda for detailed answer!

Now it is clear and I have a way to update my solution.