Github - auth_state_groups_key cannot find teams dict keys
Bug description
When configuring Jupyterhub on Kubernetes via helm and configuring the GithubOAuthenticator to populate the teams and then also utilize those teams as group it cannot find the properties. Error message:
E 2025-06-09 19:13:22.282 JupyterHub oauth2:1245] The auth_state_groups_key teams does not exist in the auth_model. Available keys are: dict_keys(['access_token', 'refresh_token', 'id_token', 'scope', 'token_response', 'github_user', 'teams'])
How to reproduce
Config
helm upgrade --cleanup-on-fail
--install jupyterhub jupyterhub/jupyterhub
--namespace jupyterhub
--create-namespace
--version=4.2.0
--values values.yaml
hub:
config:
JupyterHub:
authenticator_class: github
GitHubOAuthenticator:
client_id: "XXXX"
client_secret: "XXXX"
oauth_callback_url: "XXXX"
manage_groups: true
admin_groups:
- jupyterhub-admins
populate_teams_in_auth_state: true
auth_state_groups_key: teams
allowed_organizations:
- XXXXX
scope:
- read:org
- user:email
Expected behaviour
The Teams of the Organization from Github are validated in JupyterHub and if a User is part of the group (e.g. jupyterhub-admins) those users are granted admin permissions in JupyterHub.
Actual behaviour
Users can login since authentication is configured correctly, however every user is just a normal user. No admin permissions are granted to any user.
Your personal set up
- OS: Kubernetes v1.30.3
- Image: quay.io/jupyterhub/k8s-hub:4.2.0
- Version(s):
jupyterhub==5.3.0 oauthenticator==17.3.0
Full environment
# paste output of `pip freeze` or `conda list` here
Configuration
# jupyterhub_config.py
Logs
The error message may be misleading, since the set() call may also return a TypeError even if the key exists:
https://github.com/jupyterhub/oauthenticator/blob/6d08bf21445888193adee225d9749c1098af91ae/oauthenticator/oauth2.py#L1240-L1248
Can you add some debugging to show the values of the teams field?
Can you add some debugging to show the values of the
teamsfield?
Hello
Sorry for hijacking the thread, I have a similar issue. I have a 'groups' claim inside my id_token, so I'm trying to set auth_state_groups_key to id_token.groups. It fails with the similar The auth_state_groups_key id_token.groups does not exist in the auth_model. Available keys are: dict_keys(['access_token', 'refresh_token', 'id_token', 'scope', 'token_response', 'oauth_user']). Looking at the code, it seems that the call to reduce() is the culprit. I wonder if my auth_state is not what I expect it to be?
Coming back to your comment, what is a way to debug this? How do I make the code print the auth_state? I'm also using JupyterHub through the Helm chart and I've tried setting debug.enabled to true but that still does not give me enough info.
Edit: Well I guess I should've looked more into this. id_token is saved as a string in auth_state, so no way to get a claim out of it. I had to change my auth_state_groups_key to oauth_user.groups. That did the trick for me! cheers!
Thanks for your hint @cobotrifork !
I was trying to get the groups from Keycloak and the documentation was not very clear, but using oauth_user.<TOKEN CLAIM> worked for me, too!
@belfhi or @cobotrifork: Can you maybe give me an example of the full config? We have in the meanwhile switched to Keycloak and would like to use client roles for the authorization. Authentication works, but the parsing of the groups for the authorization fails I guess: This is the config:
hub:
config:
GenericOAuthenticator:
client_id: jupyterhub
client_secret: XXXXX
oauth_callback_url: https://jupyterhub.XXXXX.eu/hub/oauth_callback
authorize_url: https://auth.XXXXXX.eu/realms/XXXX/protocol/openid-connect/auth
token_url: https://auth.XXXXXX.eu/realms/XXXXX/protocol/openid-connect/token
userdata_url: https://auth.XXXXX.eu/realms/XXXX/protocol/openid-connect/userinfo
login_service: keycloak
username_key: preferred_username
auth_state_groups_key: oauth_user.resource_access.jupyterhub.roles
scope:
- openid
- profile
- email
- roles
manage_groups: true
allowed_groups:
- jupyterhub-admin
- jupyterhub-contributor
admin_groups:
- jupyterhub-admin
JupyterHub:
authenticator_class: generic-oauth
I also with a seperate OpenID Connect debugger looked at JWT Access Tokens / ID Tokens. In the Access Token the client roles are exactly listed under the above listed: oauth_user.resource_access.jupyterhub.roles
Any ideas?
@linkeal
where are the roles defined in your access token?
If I remember correctly, if you use auth_state_groups_key: oauth_user.resource_access.jupyterhub.roles, then I would expect the roles to be in resource_access.jupyterhub.roles of your access token. Is that the case?
Yeah exactly @cobotrifork. The decoded access token contains the resource_access attribute like this:
{
.....
Normal access token attributes
.....
"resource_access": {
"jupyterhub": {
"roles": [
"jupyterhub-admin"
]
},
"account": {
"roles": [
"manage-account",
"manage-account-links",
"view-profile"
]
}
},
.....
I think the groups are fetched from the userinfo endpoint. Are the Roles also present in the userinfo?
Indeed @belfhi. Thanks for that hint! I got it working finally. My configuration for Jupyterhub in the helm chart above was perfectly fine. However the roles were not shared in the userinfo.
Enabling that in Keycloak under Client Scopes--> roles --> Mappers tab, select client roles and setting userinfo to on. That did the trick! On that journey the openid-connect debugger here helped me to actually see that the roles were missing in the userinfo: https://github.com/rcbj/oauth2-oidc-debugger