Hello,
After configuring the AzureAdOAuthenticator to manage the groups, I see them appear in the hub admin console. I was under the impression that I could allow access to JupyterHub based on this group membership, but I can’t seem to figure it out.
My current config:
c.AzureAdOAuthenticator.allowed_groups = {‘MyGroup1’}
c.AzureAdOAuthenticator.manage_groups = True
c.AzureAdOAuthenticator.user_groups_claim = ‘groups’
If I check the Hub’s logs, i see an error message:
Config option allowed_groups
not recognized by AzureAdOAuthenticator
. Did you mean one of: allowed_users, manage_groups
?
The LocalAzureAdOAuthenticator does have this option, but that one seems to apply to local UNIX groups only. Other Authenticators (like the Google and GitHub ones) also seem to have this capability.
Any insights much appreciated!
manics
June 12, 2024, 7:08pm
2
It’s not in the current release, but a PR has just been merged
jupyterhub:main
← yuvipanda:groups-main
opened 05:27AM - 29 Mar 24 UTC
## Motivating use cases
External identity providers providing JupyterHub memb… erships is an extremely useful feature that should be present not just for `GenericOAuthenticator` but for all authenticators. But to do so in helpful ways, this PR considers two motivating use cases:
1. A hub using `Auth0OAuthenticator`. In Auth0, `scope`s granted are what is used to provide the notion of 'can the user perform this task?', which can be used as group membership. This is what auth0 recommends, there is currently no other way to do 'groups' in Auth0. `scope` is inside `auth_model`, but *not* `auth_state`, since `scope` is granted each time the user is logged in.
2. In `GitHubOAuthenticator`, we put the list of teams the user is in inside `auth_state`. This is the perfect piece of information to use for group membership.
3. `oauth_user` gets put inside `auth_state`, and in general `auth_state` is a good place for this kinda group information to be in. Authenticators can put arbitrary stuff inside `auth_state` and use them as they wish.
## Approaches considered and rejected
1. Each authenticator figures out how groups work within it. This was tried out in https://github.com/jupyterhub/oauthenticator/pull/739, and rejected by @minrk in https://github.com/jupyterhub/oauthenticator/pull/735#issuecomment-2041996689. I agree with this rejection.
2. Allow group information to be picked up from the `auth_model` with a `auth_model_groups_key`. This would be same as the current `claim_groups_key`, but pick from the entire `auth_model` instead of just from the returned user object. This was the tack this PR was taking, primarily because I thought we needed it to handle use case 1 mentioned earlier. But turns out I was wrong - I had thought that `scope` was part of `auth_model` but not `auth_state`, but we do! And regardless, I also realized we don't expose `auth_model` *anywhere*, but we *do* expose `auth_state`. And I had a TODO for 'document what is in `auth_model`', and while trying to do that, decided we shouldn't expose that to configurable tweaks like this *for now*. So that was reverted in b337015306f51a8a9ea8e95924a7562bfa1e56ba and a different approach was taken.
## Approach this PR takes
The general approach to group management is:
1. Authenticator puts something that may be relevant to group membership inside `auth_state`.
2. There's an `auth_state_groups_key` that can be either a callable or dotted specification that generates a list of groups from something in `auth_state`.
This handles case (2) because list of teams is already in `auth_state`. And can handle (1) by us putting `scope` in some form inside `auth_state`. This also provides a clear extensible mechanism in the future for all group management - get it into `auth_state` (where it can be used for anything), and pick that out with `auth_state_groups_key`.
## Backwards compatibility
- The existing `claim_groups_key` behavior is preserved, by being passed on to `auth_state_groups_key` in the base. It has been marked as deprecated. This is not a backwards compatibility break.
- All group related functionality now **requires** `manage_groups` to be `True`, which was not the case earlier. Before this, if `manage_groups` is false but any of the group related authorization functionality (`allowed_groups` and `admin_groups`) is used, they control group related behavior **but don't show up as JupyterHub groups**. This causes confusion, as the 'groups' field in the admin panel will be empty, and possible other group related behavior (such as future profile list filtering, for example) would *not* respect these groups. We basically would end up with *two* group concepts - First class JupyterHub groups (which will show up in admin panel, API, can be *edited* by admins, etc) as well as second class 'Authenticator' groups (which are only used for authorization and 'disappear' after that). I think this is unnecessary complication, and this is a good time to remove this distinction. Now, any kind of group related authorization functionality *requires* `manage_groups` to be `True`, and we are back to having only one notion of 'group'. We also remove the confusing part where you may have `allowed_groups` set to something, manually modify the groups the user is a part of in JupyterHub admin, and it silently has no effect. This is a *breaking change* for people who used groups functionality but set `manage_groups` to be `False`. However, I think that usage is fairly minor, because of the confusing behavior it causes. I have added the 'breaking' label here regardless.
## Breaking change
- All group related functionality (`allowed_groups`, `admin_groups`, `claims_group_key` and `auth_state_groups_key`) now also requires `manage_groups` to be set to `True`
## TODO
- [x] Update docs to refer to new property
- [x] Reword the docstring for `auth_state_groups_key`
Fixes https://github.com/jupyterhub/oauthenticator/issues/709
You should be able to test it by installing the main branch: pip install git+https://github.com/jupyterhub/oauthenticator.git@main
1 Like