In JupyterHub, is it possible to disable the ‘Never’ option for user API token generation? Or hide the Token tab in the menu for non-admin users?
I was also thinking about creating a custom user role with read:tokens
, or digging deeper into expiry settings (though at a glance they didn’t seem like they would apply to this).
I primarily don’t want users creating API tokens that never expire.
3 Likes
Looks like this was requested here:
opened 09:46PM - 02 Sep 22 UTC
enhancement
JupyterHub has a [REST API](https://jupyterhub.readthedocs.io/en/stable/referenc… e/rest.html) that can be accessed using an API token. The API token can be created at in the Hub UI at `/hub/token` or through a [POST](https://jupyterhub.readthedocs.io/en/stable/reference/rest-api.html#/default/post_users__name__tokens) to the REST API itself. In the Hub UI a user can create a token with expiration of 1 day, 1 week, 1 month, or never. The API allows a user to set an arbitrary value for expiration. A user's tokens can be revoked by the user or by a user with the ability to revoke their tokens (e.g. an admin).
I was wondering what controls JupyterHub admins have or could have to mitigate risk from lost or stolen JupyterHub REST API tokens. I'm opening this issue to capture discussion about potential controls to implement in JupyterHub, or that may already be available. Some of this has been scoped out with @minrk.
In terms of remediation, if a user's token is known to be compromised, their accounts are possibly already locked and they may not have a way to revoke their own tokens. If an admin is informed that a user's token is compromised, they can delete the user from their Hub, use `python -m jupyterhub.dbutil shell` to remove the token, or make an API call to revoke the user's token. It may be a good idea to add to the Hub UI some way for users who can revoke other users' tokens a way to do that. This could be done by updating the URL scheme so such a user (e.g. an admin) can see another user's `/hub/token` page to do the revocation.
In terms of more preemptive mitigations, might there be ways for admins to:
1. Disable generation of these general-purpose tokens altogether?
2. Enable generation of only more restrictively scoped tokens (a more restricted user role)?
3. Enforce a maximum lifetime for these general-purpose tokens, necessitating a re-auth?
4. Only allow token access from specified IP ranges?
Option 1 works already through JupyterHub RBAC by replacing the default `user` role with one that cannot create API tokens. Thanks to Min for enumerating all the scopes here:
```
c.JupyterHub.load_roles = [
{
"name": "user",
"scopes": [
# read the user model
"read:users!user",
# manage the user's servers
"servers!user",
# access the user's servers
"access:servers!user",
# update activity (required for server activity)
"users:activity!user",
# keep read-only access to tokens
# can't add or revoke tokens!
"read:tokens!user",
]
}
]
```
With this redefined `user` role, attempts to create a token fail with 403 Forbidden. Other tokens that are needed to operate notebooks and services still work just fine. This solution seems like a good one for folks who need to require their users to re-authenticate periodically to interact with Jupyter/JupyterHub. This may be worth including as documentation via example, and referencing that example from JupyterHub's RBAC and security docs?
Option 2 is a little bit different from the above which just shuts off the ability to generate tokens. There might be some argument that users could have the ability to generate more restricted tokens and that's somehow OK. Are there use cases where that makes sense, and what kind of interface would be needed to manage all the different things you could pick and choose?
Option 3 is something that is not possible now technically (this has been discussed previously in #1772 as well). It is something Min says he would like to be able to address as part of a better singleuser experience.
I went into this favoring Option 4 personally, just allowing users to use tokens from specified IP ranges, but Min pointed out that mileage may vary due to issues with reverse proxying. If one were to try this it may just be best to do it at the edge or where SSL is terminated.
Do folks have other thoughts, opinions, or other options?
1 Like