p2-inc / keycloak-orgs

Single realm, multi-tenancy for SaaS apps
https://phasetwo.io
Other
389 stars 66 forks source link

org_id claim not mapped when using the User Session Note mapper as explained in the docs #36

Closed maxhov closed 1 year ago

maxhov commented 1 year ago

I am exploring your great product and it seems like a very interesting proposition. However, we are currently hitting some bumps. To discriminate between organisations, we would require a claim in the id/access tokens. An explanation is given how to do it with a User Session Note mapper, but I was unable to get it working.

My setup looks as follows:

In the 'App' realm I created an organisation called 'test' with a mapped domain 'test.com' and a Keycloak identity provider that links to the 'Client' realm. This way the 'org_id' could be resolved via the identity provider used, or at least that is how I understand it should work. Please correct me if I am misunderstanding.

Next, the flow I am currently testing is a simple SPA application redirects the user to the realm 'App' which starts the authentication flow. This is realized through a client registration called 'spa', which has the User Session Note Mapper configured as dedicated scope. It maps the 'org_id' note to the claim 'org_id' as defined in the example in the docs.

Now, when I login with a user in the Client realm, the authentication succeeds and I can also map organisation roles and attributes into the tokens (id and access). However, I cannot get the User Session Note mapper to work in order to map the org_id claim into the token.

After some debugging of the code at work, I noticed that the 'org_id' is set into the AuthenticationSessionModel as AuthNote (at this point the 'org_id' is resolved correctly). However, when creating the tokens and consequently in the UserSessionNoteMapper class, the claim cannot be resolved from the UserSession. When I inspect all UserSession notes, it also seems the 'org_id' note is missing.

I am using the following Docker image: quay.io/phasetwo/phasetwo-keycloak:20.0.3.1675013801

Hopefully it is somewhat clear what the test setup is and which issue I am experiencing. Let me know if I can clarify.

xgp commented 1 year ago

I don't know that I'm 100% understanding your use case, but I think you're right. We might have to add setting a user session note in OrgNoteAuthenticatorFactory in order to fit your needs.

maxhov commented 1 year ago

Ah yes. My use case is: I would like to get the organisation id of the organisation the user is currently logged into mapped into the acces and id tokens.

xgp commented 1 year ago

This should probably work for your use case: https://github.com/p2-inc/keycloak-orgs/pull/37

maxhov commented 1 year ago

This should probably work for your use case: #37

Definitely! That should do the trick.

Somewhat related to this question, I was wondering another use case and how to solve it (I am happy to create a separate issue for it to keep this thread clean).

What is the suggested approach to logging in a user that is a member of multiple organisations? In the current situation, I think this needs to be solved outside of Phase Two? How I understand it, in the current setup, the user needs to be member of the primary IdP of the other organisation in order to be able to login to the organisation and have an 'org_id' resolved for it?

I could imagine that in the future, after login, the user is presented an organisation selection screen that allows the user to select which organisation the user wants to login to? Probably that logic would have to consider only organisations that have the same IdP configured for it. Maybe with a login hint this selection screen could be skipped. Anyway, just thinking out loud how this could be enabled.

xgp commented 1 year ago

We do that in our self-service product. There are two mappers that might help you, for organization roles and attributes. Both can add a claim that contains all the organizations that the user is a member of, and either their roles in that organization or the attributes for that organization.

image

We use that to present the user with a "selector" for organizations they are a member of.

xgp commented 1 year ago

In the case of doing it before the user has logged in, that's been suggested as a feature, and is certainly possible using a custom Authenticator and flow, but it hasn't been done yet. Happy to accept PRs in that regard.

maxhov commented 1 year ago

Thank you for merging the PR so quickly.

We do that in our self-service product. There are two mappers that might help you, for organization roles and attributes. Both can add a claim that contains all the organizations that the user is a member of, and either their roles in that organization or the attributes for that organization.

image

We use that to present the user with a "selector" for organizations they are a member of.

Ah ok, understood. Does that also work for users that do not authenticate via a (primary) IdP and directly authenticate to the realm of the application? Because currently there is no way to get the org_id set in the token for users that do not authenticate via a primary IdP.

maxhov commented 1 year ago

This should probably work for your use case: #37

I have built a plain Keycloak image with the newly released keycloak-orgs JAR (v0.7) and I can confirm it works :).