mirror of
https://github.com/jupyterhub/jupyterhub.git
synced 2025-10-17 23:13:00 +00:00
support specifying token permissions in UI
- add scopes field to token form - add permissions column to token tables - expand docs on specifying token scopes, including api example
This commit is contained in:
@@ -552,7 +552,11 @@ paths:
|
||||
- oauth2:
|
||||
- read:tokens
|
||||
post:
|
||||
summary: Create a new token for the user
|
||||
summary: |
|
||||
Create a new token for the user.
|
||||
Permissions can be limited by specifying a list of `scopes` in the JSON request body
|
||||
(starting in JupyerHub 3.0; previously, permissions could be specified as `roles` could be specified,
|
||||
which is deprecated in 3.0).
|
||||
parameters:
|
||||
- name: name
|
||||
in: path
|
||||
|
@@ -99,9 +99,46 @@ In JupyterHub 2.0,
|
||||
specific permissions are now defined as '**scopes**',
|
||||
and can be assigned both at the user/service level,
|
||||
and at the individual token level.
|
||||
The previous behavior is represented by the scope `inherit`,
|
||||
and is still the default behavior for requesting a token if limited permissions are not specified.
|
||||
|
||||
This allows e.g. a user with full admin permissions to request a token with limited permissions.
|
||||
|
||||
In JupyterHub 5.0, you can specify scopes for a token when requesting it via the `/hub/tokens` page as a space-separated list.
|
||||
In JupyterHub 3.0 and later, you can also request tokens with limited scopes via the JupyterHub API (provided you already have a token!):
|
||||
|
||||
```python
|
||||
import json
|
||||
from urllib.parse import quote
|
||||
|
||||
import requests
|
||||
|
||||
def request_token(
|
||||
username, *, api_token, scopes=None, expires_in=0, hub_url="http://127.0.0.1:8081"
|
||||
):
|
||||
"""Request a new token for a user"""
|
||||
request_body = {}
|
||||
if expires_in:
|
||||
request_body["expires_in"] = expires_in
|
||||
if scopes:
|
||||
request_body["scopes"] = scopes
|
||||
url = hub_url.rstrip("/") + f"/hub/api/users/{quote(username)}/tokens"
|
||||
r = requests.post(
|
||||
url,
|
||||
data=json.dumps(request_body),
|
||||
headers={"Authorization": f"token {api_token}"},
|
||||
)
|
||||
if r.status_code >= 400:
|
||||
# extract error message for nicer error messages
|
||||
r.reason = r.json().get("message", r.text)
|
||||
r.raise_for_status()
|
||||
# response is a dict and will include the token itself in the 'token' field,
|
||||
# as well as other fields about the token
|
||||
return r.json()
|
||||
|
||||
request_token("myusername", scopes=["list:users"], api_token="abc123")
|
||||
```
|
||||
|
||||
## Updating to admin services
|
||||
|
||||
```{note}
|
||||
|
@@ -300,6 +300,11 @@ Custom scope _filters_ are NOT supported.
|
||||
|
||||
### Scopes and APIs
|
||||
|
||||
The scopes are also listed in the [](jupyterhub-rest-API) documentation. Each API endpoint has a list of scopes which can be used to access the API; if no scopes are listed, the API is not authenticated and can be accessed without any permissions (i.e., no scopes).
|
||||
The scopes are also listed in the [](jupyterhub-rest-API) documentation.
|
||||
Each API endpoint has a list of scopes which can be used to access the API;
|
||||
if no scopes are listed, the API is not authenticated and can be accessed without any permissions (i.e., no scopes).
|
||||
|
||||
Listed scopes by each API endpoint reflect the "lowest" permissions required to gain any access to the corresponding API. For example, posting user's activity (_POST /users/:name/activity_) needs `users:activity` scope. If scope `users` is passed during the request, the access will be granted as the required scope is a subscope of the `users` scope. If, on the other hand, `read:users:activity` scope is passed, the access will be denied.
|
||||
Listed scopes by each API endpoint reflect the "lowest" permissions required to gain any access to the corresponding API.
|
||||
For example, posting user's activity (_POST /users/:name/activity_) needs `users:activity` scope.
|
||||
If scope `users` is held by the request, the access will be granted as the required scope is a subscope of the `users` scope.
|
||||
If, on the other hand, `read:users:activity` scope is the only scope held, the request will be denied.
|
||||
|
Reference in New Issue
Block a user