BookStackApp / BookStack

A platform to create documentation/wiki content built with PHP & Laravel
https://www.bookstackapp.com/
MIT License
15.43k stars 1.94k forks source link

Behaviour of OIDC group sync #5192

Closed RZR7332 closed 1 month ago

RZR7332 commented 2 months ago

Attempted Debugging

Searched GitHub Issues

Describe the Scenario

Hi Dan,

I think this is more a case of me overthinking, or not quite understanding how the whole setup works properly. I migrated my BookStack setup recently to OIDC fairly smoothly, but there is something odd in the behaviour of the group sync which does not make sense to me (likely a user problem here).

From the documentation:

BookStack has the ability to sync OIDC user groups with BookStack roles. By default this will match OIDC group names with the BookStack role display names with casing ignored. This can be overridden by via the ‘External Authentication IDs’ field which can be seen when editing a role while OIDC authentication is enabled.

This to me implies that the group names will be ignored if the External Authentication ID field is set - which it is. I followed the guide to map my already existing user to the user created on Keycloak by using that field, which works perfectly. I have also configured my .env file as below:

! Enable OIDC group sync.
OIDC_USER_TO_GROUPS=true

! Set the attribute from which BookStack will read groups names from.
OIDC_GROUPS_CLAIM=groups

! Additional scopes to send with the authentication request.
! By default BookStack only sends the 'openid', 'profile' & 'email' scopes.
! Many platforms require specific scopes to be requested for group data.
! Multiple scopes can be added via comma separation.
! Comment out unless this is used, as this will break the redirection/integration
! and throw an unknown error which can be viewed in the URL.
!OIDC_ADDITIONAL_SCOPES=roles
! Remove the user from roles that don't match OIDC groups upon login.
! Note: While this is enabled the "Default Registration Role", editable within the 
! BookStack settings view, will be considered a matched role and assigned to the user.
OIDC_REMOVE_FROM_GROUPS=false

This also seems to work correctly as the below is returned from Keycloak after creating a custom attribute and mapping (tested by dumping user details):

"groups": "Admin",

By my logic, this should match the Admin role within BookStack and assign it to my user, which seems to be fine.

My issue comes in when I enable OIDC_REMOVE_FROM_GROUPS - as soon as that is set to true, when I log in my user has no permissions at all - so I am seemingly hitting the default role/permissions here.

Have I missed or misunderstood something in terms of how the process works?

Exact BookStack Version

v24.05.4

Log Content

No response

Hosting Environment

Installed using official installation script.

ssddanbrown commented 2 months ago

:wave: Hi @RZR7332,

This also seems to work correctly as the below is returned from Keycloak after creating a custom attribute and mapping (tested by dumping user details):

That output isn't what I'd expect from the OIDC system for groups. BookStack expects to see an array of groups under the given claim, instead of the simple single string value that currently appears to be returned there.

RZR7332 commented 2 months ago

Hi Dan,

I omitted a lot of info, the full token looks as below (values redacted):

{ "exp": REDACTED, "iat": REDACTED, "auth_time": REDACTED, "jti": "REDACTED", "iss": "REDACTED", "aud": "bookstack", "sub": "REDACTED", "typ": "ID", "azp": "bookstack", "sid": "REDACTED", "at_hash": "REDACTED", "acr": "1", "email_verified": true, "name": "REDACTED", "groups": "Admin", "preferred_username": "REDACTED", "given_name": "REDACTED", "family_name": "REDACTED", "email": "REDACTED" }

However, I take your point. Based on this, would you agree that group sync is in fact not working at all in my case and login is merely using the group/role which has been statically assigned to the user?

I must have missed something somewhere, will keep reading and digging.

ssddanbrown commented 2 months ago

However, I take your point. Based on this, would you agree that group sync is in fact not working at all in my case and login is merely using the group/role which has been statically assigned to the user?

Yeah, that's likely.

Looking at the answer here it looks like it should be possible via a "Groups Mapper"?: https://stackoverflow.com/questions/56362197/keycloak-oidc-retrieve-user-groups-attributes

RZR7332 commented 2 months ago

Thanks Dan, had a very quick look and it seems similar to what I have done (I added a custom attribute and mapped it to the application). Will set aside some time this week to work through it and see where the mismatch is.

Much appreciated!

RZR7332 commented 1 month ago

As suspected, I was the problem: I was operating under the understanding that as long as the correct string/text was present in the token, it would be mapped correctly - this was a mistake. My initial test for group sync was done with user attributes in Keycloak, which clearly did not work.

Thanks to inspiration from another issue (https://github.com/BookStackApp/BookStack/issues/3004#issuecomment-1197974958), the correct sequence of events should be similar to the below:

  1. Create client-specific role, e.g. Admin.
  2. Map your user to that role.
  3. Under the [client]-dedicated scope, configure a new mapper and choose User Client Role.

This should return a Token Claim Name of resource_access.${client_id}.roles which is the correct and expected claim.

Thanks for the patience and help, hope this helps someone in the future.

ssddanbrown commented 1 month ago

@RZR7332 Good to hear you found a solution and got things working!