Add scopes to `JUPYTERHUB_API_TOKEN` through Helm chart values

Good afternoon,

I’ve recently updated to chart version 2.0.0 of JupyterHub (app version 3.0.0) from the repository at See installation instructions for: | JupyterHub’s Helm chart repository.

Unlike previous versions, the JUPYTERHUB_API_TOKEN now has limited scopes due to the use of the service role, so I’m unable to mange groups through the API with that token (missing the admin:groups scope).

This post was very useful and I totally understand why this is happening and I’m on board with the use or RBAC. However, because I use a Helm chart to install JupyterHub, I don’t have any configuration file that I can change to add the required scopes to the JUPYTERHUB_API_TOKEN. Is it possible to do this through the use of Helm chart values, or any other way at all?

Thanks,
David

You should be able to modify the roles using hub.loadRoles:

1 Like

Thank you for pointing me in the right direction, I was able to do what I needed by adding the following to my values file.

hub:
  loadRoles:
    server:
      scopes: [self, admin:groups]

Edit: I’ve ended up having to use inherit, because Jupyter will try to assign the admin:groups scope to all users, so the spawner will fail for non-admin users. This is quite frustrating, because it now means that the server token has all of the scopes of the user, which kind of negates the point of RBAC.

hub:
  loadRoles:
    server:
      scopes: [inherit]

I’m not sure how your use of admin:groups works, but it’s possible that you should use the token for requests, which are associated with each user, rather than the server itself. These scopes are more flexible, and will actually resolve to the subset held by the user (I think we can probably do the same for the server token, after some changes in 3.0, but haven’t done this yet). Can you describe more how you use this scope?

To specify the scopes of the request token, set c.Spawner.oauth_client_allowed_scopes, which is what will be requested as you oauth with the single-user server. You can then use this in a request handler (token = hub_auth.get_token(handler)).

I think that the changes to token scopes in 3.0 should probably be extended to the server token, which should enable this same flexibility (config expresses the limit of scopes, but intersect with those of the user before assigning, rather than failing), and that might just do what you were expecting in the first place.

Hi @minrk , thanks for your reply.

To give you a little more context… We have a Notebook that contains several cells to allow Admin users to interact with the Jupyter API, specifically groups. To do this, we have one cell that sets the Authorization header and API URL, and then a series of other cells to do things like create groups and list users in, add users to, and remove users from those groups.

So the reason for wanting the JUPYTERHUB_API_TOKEN to contain the relevant scopes is so that we don’t have to generate a token and place it in the Notebook each time one of those cells is run. Not only is it easier, it saves the possibility of a token being exposed to a non-admin users.

In an ideal world, we like to say “give the JUPYTERHUB_API_TOKEN the admin:groups scope if the user has that scope, otherwise don’t”. This may be what you are suggesting with c.Spawner.oauth_client_allowed_scopes, but you’ll have to forgive me as I’m pretty new to Jupyter so I’m not sure if that’s the case. But either way, we have the ability to inherit, which while not ideal as it gives more scopes than required to JUPYTERHUB_API_TOKEN, it does allow us to achieve our goal.

Thanks,
David

That use case definitely makes sense, and it is definitely harder to pass the browser token to the kernel! Not impossible, but you’d need something custom to do it, e.g. a JupyterLab extension to send the token via a getpass call.

This may be what you are suggesting

I believe so, and it’s definitely what we should do. In 3.1, we do this we tokens requested elsewhere, and it would be more consistent to do this with JUPYTERHUB_API_TOKEN. This change adds a Spawner.server_token_scopes config that is simpler, more flexible, and essentially replaces the server role.

That change looks to be exactly what we’d need, so if that becomes available it’s defiantly something we’d go for.

Many thanks,
David