jupyterhub / oauthenticator

OAuth + JupyterHub Authenticator = OAuthenticator
https://oauthenticator.readthedocs.io
BSD 3-Clause "New" or "Revised" License
408 stars 362 forks source link

`cognito:groups` claim_groups_key not present in the user_info object passed to c.GenericOAuthenticator.claim_groups_key #738

Closed banson-aiq closed 4 months ago

banson-aiq commented 5 months ago

Bug description

Follow up to https://discourse.jupyter.org/t/control-admin-group-membership-from-an-aws-cognito-user-group/24508/7

I am attempting to use claim_groups_key to identify what AWS Cognito groups a user belongs to. Initially I am using this to identify admin users. Authentication with cognito works, but I am unable to get the cognito:groups to be visible to JupyterHub. I have tested the cognito configuration separately using aws cli like so

aws cognito-idp initiate-auth --auth-flow USER_PASSWORD_AUTH --auth-parameters "USERNAME=user1@testing.com,PASSWORD=xxxxxxx,SECRET_HASH=yyyyyyyyyy" --client-id aaaaaaaaa

In these tests I do see cognito:groups in the Id Token and Access Token, so I concluded that there must be a JupyterHub configuration issue or bug.

How to reproduce

  1. Setup AWS Cognos
    • OAuth grant type = Authorization code grant
    • scopes = openid, profile, aws.cognito.signin.user.admin
    • create a user
    • create a group called admin add the user to the group
  2. Setup JupyterHub Kubernetes config.yaml
    
    debug:
    enabled: true

singleuser: defaultUrl: "/lab" extraEnv: JUPYTERHUB_SINGLEUSER_APP: "jupyter_server.serverapp.ServerApp" profileList:

ingress: enabled: true hosts:


4. Login the test user
6. See error

User sees `500 : Internal Server Error`

In the pod logs I see this which shows the user_info object with the cognito:groups property missing

{'sub': 'xxxxxxxxxxxxxxxx', 'email_verified': 'true', 'preferred_username': 'user1', 'email': 'user1@myhost.com', 'username': 'eeeeeeeeeeeeeeee'}

[E 2024-04-04 08:26:11.852 JupyterHub web:1871] Uncaught exception GET /hub/oauth_callback?code=cf5e4585-5fe8-4253-8711-78871e2391c7&state=eyJzdGF0ZV9pZCI6ICIwNTM2MmM2MWVlMzQ0ZDdkOTNjNjdjNjI5MjdmYTAxNSJ9 (::ffff:172.31.36.247) HTTPServerRequest(protocol='http', host='myhost.com', method='GET', uri='/hub/oauth_callback?code=cf5e4585-5fe8-4253-8711-78871e2391c7&state=eyJzdGF0ZV9pZCI6ICIwNTM2MmM2MWVlMzQ0ZDdkOTNjNjdjNjI5MjdmYTAxNSJ9', version='HTTP/1.1', remote_ip='::ffff:172.31.36.247') Traceback (most recent call last): File "/usr/local/lib/python3.11/site-packages/tornado/web.py", line 1786, in _execute result = await result ^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/oauthenticator/oauth2.py", line 208, in get user = await self.login_user() ^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/jupyterhub/handlers/base.py", line 828, in login_user authenticated = await self.authenticate(data) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/jupyterhub/auth.py", line 492, in get_authenticated_user authenticated = await maybe_future(self.authenticate(handler, data)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/oauthenticator/oauth2.py", line 995, in authenticate return await self.update_auth_model(auth_model) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/oauthenticator/generic.py", line 161, in update_auth_model user_groups = self.get_user_groups(user_info) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/oauthenticator/generic.py", line 138, in get_user_groups return set(self.claim_groups_key(user_info)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "", line 3, in debug_claim_groups_key KeyError: 'cognito:groups'



#### Expected behaviour

I expect the user_info in JupyterHub to contain the cognito:groups property

#### Actual behaviour

See error above

### Your personal set up

zero-to-jupyterhub
jupyterhub helm chart version: 3.2.1

AWS EKS - kubernetes version 1.29
welcome[bot] commented 5 months ago

Thank you for opening your first issue in this project! Engagement like this is essential for open source projects! :hugs:
If you haven't done so already, check out Jupyter's Code of Conduct. Also, please try to follow the issue template as it helps other other community members to contribute more effectively. welcome You can meet the other Jovyans by joining our Discourse forum. There is also an intro thread there where you can stop by and say Hi! :wave:
Welcome to the Jupyter community! :tada:

welcome[bot] commented 5 months ago

Thank you for opening your first issue in this project! Engagement like this is essential for open source projects! :hugs:
If you haven't done so already, check out Jupyter's Code of Conduct. Also, please try to follow the issue template as it helps other other community members to contribute more effectively. welcome You can meet the other Jovyans by joining our Discourse forum. There is also an intro thread there where you can stop by and say Hi! :wave:
Welcome to the Jupyter community! :tada:

banson-aiq commented 4 months ago

This is now resolved in never versions of oauthenticator and jupyterhub. For anyone stumbling across this...

Root cause was older versions of oauthenticator relied on the userInfo api to fetch groups. However in AWS Cognito the groups are only returned as part of the IdToken and AccessToken. So a change was needed to switch the oauthenticator to use the tokens for the groups (an other user profile items). This was made possible by https://github.com/jupyterhub/oauthenticator/pull/725/commits/3ce840988c0a7c455302ad2f6521eca57b34120e

So now all you need to do is ensure these are set in your helm config

hub:
  config:
    GenericOAuthenticator:
      client_id: xxxxxxxxxxxxxxxxx
      client_secret: xxxxxxxxxxxxxxxxxxxxxxxxxxx
      oauth_callback_url: xxxxxxxxxxxxxxxxxxxxxxxxxx
      authorize_url: xxxxxxxxxxxxxx/oauth2/authorize
      token_url: xxxxxxxxxxxxxx/oauth2/token
      logout_redirect_url: xxxxxxxxxxxxxxxxxxxxxxxxxxxx
      auto_login: True
      allow_all: True
      manage_groups: True
      enable_auth_state: True
      userdata_from_id_token: True
      scope:
        - openid
        - profile
        - aws.cognito.signin.user.admin
      username_claim: preferred_username
      login_service: 'AWS Cognito'
      claim_groups_key: cognito:groups
      admin_groups:
        - admin
    JupyterHub:
      authenticator_class: generic-oauth
  extraConfig:
    nbuserConfig: |
      import secrets
      os.environ['JUPYTERHUB_CRYPT_KEY'] = secrets.token_hex(111)
consideRatio commented 4 months ago

Thank you for examplifying and summarizing your insights about this @banson-aiq!!! :heart: :tada:

I think on z2jh deployed hubs, you don't need to set ceypt key stuff yourself @banson-aiq - it should be generated once and saved for you automatically. (Exception if you deploy with argo etc perhaps)