mirror of
https://github.com/jupyterhub/jupyterhub.git
synced 2025-10-16 14:33:00 +00:00
refine service auth docs
favor HubOAuth, as that should really be the default for most services - Remove some outdated 'new in' text - Remove docs for some deprecated features (hub_users, hub_groups) - more detail on what's required
This commit is contained in:
@@ -103,6 +103,8 @@ parameters, which describe the environment needed to start the Service process:
|
|||||||
|
|
||||||
The Hub will pass the following environment variables to launch the Service:
|
The Hub will pass the following environment variables to launch the Service:
|
||||||
|
|
||||||
|
(service-env)=
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
JUPYTERHUB_SERVICE_NAME: The name of the service
|
JUPYTERHUB_SERVICE_NAME: The name of the service
|
||||||
JUPYTERHUB_API_TOKEN: API token assigned to the service
|
JUPYTERHUB_API_TOKEN: API token assigned to the service
|
||||||
@@ -184,18 +186,38 @@ extra slash you might get unexpected behavior. For example if your service has a
|
|||||||
|
|
||||||
## Hub Authentication and Services
|
## Hub Authentication and Services
|
||||||
|
|
||||||
JupyterHub 0.7 introduces some utilities for using the Hub's authentication
|
JupyterHub provides some utilities for using the Hub's authentication
|
||||||
mechanism to govern access to your service. When a user logs into JupyterHub,
|
mechanism to govern access to your service.
|
||||||
the Hub sets a **cookie (`jupyterhub-services`)**. The service can use this
|
|
||||||
cookie to authenticate requests.
|
|
||||||
|
|
||||||
JupyterHub ships with a reference implementation of Hub authentication that
|
Requests to all JupyterHub services are made with OAuth tokens.
|
||||||
|
These can either be requests with a token in the `Authorization` header,
|
||||||
|
or url parameter `?token=...`,
|
||||||
|
or browser requests which must complete the OAuth authorization code flow,
|
||||||
|
which results in a token that should be persisted for future requests
|
||||||
|
(persistence is up to the service,
|
||||||
|
but an encrypted cookie confined to the service path is appropriate,
|
||||||
|
and provided by default).
|
||||||
|
|
||||||
|
:::{versionchanged} 2.0
|
||||||
|
The shared `jupyterhub-services` cookie is removed.
|
||||||
|
OAuth must be used to authenticate browser requests with services.
|
||||||
|
:::
|
||||||
|
|
||||||
|
JupyterHub includes a reference implementation of Hub authentication that
|
||||||
can be used by services. You may go beyond this reference implementation and
|
can be used by services. You may go beyond this reference implementation and
|
||||||
create custom hub-authenticating clients and services. We describe the process
|
create custom hub-authenticating clients and services. We describe the process
|
||||||
below.
|
below.
|
||||||
|
|
||||||
The reference, or base, implementation is the [`HubAuth`][hubauth] class,
|
The reference, or base, implementation is the [`HubAuth`][hubauth] class,
|
||||||
which implements the requests to the Hub.
|
which implements the API requests to the Hub that resolve a token to a User model.
|
||||||
|
|
||||||
|
There are two levels of authentication with the Hub:
|
||||||
|
|
||||||
|
- [`HubAuth`][hubauth] - the most basic authentication,
|
||||||
|
for services that should only accept API requests authorized with a token.
|
||||||
|
|
||||||
|
- [`HubOAuth`][huboauth] - For services that should use oauth to authenticate with the Hub.
|
||||||
|
This should be used for any service that serves pages that should be visited with a browser.
|
||||||
|
|
||||||
To use HubAuth, you must set the `.api_token`, either programmatically when constructing the class,
|
To use HubAuth, you must set the `.api_token`, either programmatically when constructing the class,
|
||||||
or via the `JUPYTERHUB_API_TOKEN` environment variable.
|
or via the `JUPYTERHUB_API_TOKEN` environment variable.
|
||||||
@@ -238,18 +260,17 @@ for more details.
|
|||||||
### Authenticating tornado services with JupyterHub
|
### Authenticating tornado services with JupyterHub
|
||||||
|
|
||||||
Since most Jupyter services are written with tornado,
|
Since most Jupyter services are written with tornado,
|
||||||
we include a mixin class, [`HubAuthenticated`][hubauthenticated],
|
we include a mixin class, [`HubOAuthenticated`][huboauthenticated],
|
||||||
for quickly authenticating your own tornado services with JupyterHub.
|
for quickly authenticating your own tornado services with JupyterHub.
|
||||||
|
|
||||||
Tornado's `@web.authenticated` method calls a Handler's `.get_current_user`
|
Tornado's {py:func}`~.tornado.web.authenticated` decorator calls a Handler's {py:meth}`~.tornado.web.RequestHandler.get_current_user`
|
||||||
method to identify the user. Mixing in `HubAuthenticated` defines
|
method to identify the user. Mixing in {class}`.HubAuthenticated` defines
|
||||||
`get_current_user` to use HubAuth. If you want to configure the HubAuth
|
{meth}`~.HubAuthenticated.get_current_user` to use HubAuth. If you want to configure the HubAuth
|
||||||
instance beyond the default, you'll want to define an `initialize` method,
|
instance beyond the default, you'll want to define an {py:meth}`~.tornado.web.RequestHandler.initialize` method,
|
||||||
such as:
|
such as:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
class MyHandler(HubAuthenticated, web.RequestHandler):
|
class MyHandler(HubOAuthenticated, web.RequestHandler):
|
||||||
hub_users = {'inara', 'mal'}
|
|
||||||
|
|
||||||
def initialize(self, hub_auth):
|
def initialize(self, hub_auth):
|
||||||
self.hub_auth = hub_auth
|
self.hub_auth = hub_auth
|
||||||
@@ -259,14 +280,21 @@ class MyHandler(HubAuthenticated, web.RequestHandler):
|
|||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
The HubAuth will automatically load the desired configuration from the Service
|
The HubAuth class will automatically load the desired configuration from the Service
|
||||||
environment variables.
|
[environment variables](service-env).
|
||||||
|
|
||||||
If you want to limit user access, you can specify allowed users through either the
|
:::{versionchanged} 2.0
|
||||||
`.hub_users` attribute or `.hub_groups`. These are sets that check against the
|
|
||||||
username and user group list, respectively. If a user matches neither the user
|
Access scopes are used to govern access to services.
|
||||||
list nor the group list, they will not be allowed access. If both are left
|
Prior to 2.0,
|
||||||
undefined, then any user will be allowed.
|
sets of users and groups could be used to grant access
|
||||||
|
by defining `.hub_groups` or `.hub_users` on the authenticated handler.
|
||||||
|
These are ignored if the 2.0 `.hub_scopes` is defined.
|
||||||
|
:::
|
||||||
|
|
||||||
|
:::{seealso}
|
||||||
|
{meth}`.HubAuth.check_scopes`
|
||||||
|
:::
|
||||||
|
|
||||||
### Implementing your own Authentication with JupyterHub
|
### Implementing your own Authentication with JupyterHub
|
||||||
|
|
||||||
@@ -316,7 +344,7 @@ and taking note of the following process:
|
|||||||
```python
|
```python
|
||||||
{
|
{
|
||||||
"name": "inara",
|
"name": "inara",
|
||||||
# groups may be omitted, depending on permissions
|
# groups may be omitted, depending on permissions
|
||||||
"groups": ["serenity", "guild"],
|
"groups": ["serenity", "guild"],
|
||||||
# scopes is new in JupyterHub 2.0
|
# scopes is new in JupyterHub 2.0
|
||||||
"scopes": [
|
"scopes": [
|
||||||
@@ -342,9 +370,11 @@ section on securing the notebook viewer.
|
|||||||
|
|
||||||
[requests]: http://docs.python-requests.org/en/master/
|
[requests]: http://docs.python-requests.org/en/master/
|
||||||
[services_auth]: ../api/services.auth.html
|
[services_auth]: ../api/services.auth.html
|
||||||
|
[hubauth]: ../api/services.auth.html#jupyterhub.services.auth.HubAuth
|
||||||
[huboauth]: ../api/services.auth.html#jupyterhub.services.auth.HubOAuth
|
[huboauth]: ../api/services.auth.html#jupyterhub.services.auth.HubOAuth
|
||||||
[hubauth.user_for_token]: ../api/services.auth.html#jupyterhub.services.auth.HubAuth.user_for_token
|
[hubauth.user_for_token]: ../api/services.auth.html#jupyterhub.services.auth.HubAuth.user_for_token
|
||||||
[hubauthenticated]: ../api/services.auth.html#jupyterhub.services.auth.HubAuthenticated
|
[hubauthenticated]: ../api/services.auth.html#jupyterhub.services.auth.HubAuthenticated
|
||||||
|
[huboauthenticated]: ../api/services.auth.html#jupyterhub.services.auth.HubOAuthenticated
|
||||||
[nbviewer example]: https://github.com/jupyter/nbviewer#securing-the-notebook-viewer
|
[nbviewer example]: https://github.com/jupyter/nbviewer#securing-the-notebook-viewer
|
||||||
[fastapi example]: https://github.com/jupyterhub/jupyterhub/tree/HEAD/examples/service-fastapi
|
[fastapi example]: https://github.com/jupyterhub/jupyterhub/tree/HEAD/examples/service-fastapi
|
||||||
[fastapi]: https://fastapi.tiangolo.com
|
[fastapi]: https://fastapi.tiangolo.com
|
||||||
|
@@ -3,10 +3,24 @@
|
|||||||
Tokens are sent to the Hub for verification.
|
Tokens are sent to the Hub for verification.
|
||||||
The Hub replies with a JSON model describing the authenticated user.
|
The Hub replies with a JSON model describing the authenticated user.
|
||||||
|
|
||||||
``HubAuth`` can be used in any application, even outside tornado.
|
This contains two levels of authentication:
|
||||||
|
|
||||||
``HubAuthenticated`` is a mixin class for tornado handlers that should
|
- :class:`HubOAuth` - Use OAuth 2 to authenticate browsers with the Hub.
|
||||||
authenticate with the Hub.
|
This should be used for any service that should respond to browser requests
|
||||||
|
(i.e. most services).
|
||||||
|
|
||||||
|
- :class:`HubAuth` - token-only authentication, for a service that only need to handle token-authenticated API requests
|
||||||
|
|
||||||
|
The ``Auth`` classes (:class:`HubAuth`, :class:`HubOAuth`)
|
||||||
|
can be used in any application, even outside tornado.
|
||||||
|
They contain reference implementations of talking to the Hub API
|
||||||
|
to resolve a token to a user.
|
||||||
|
|
||||||
|
The ``Authenticated`` classes (:class:`HubAuthenticated`, :class:`HubOAuthenticated`)
|
||||||
|
are mixins for tornado handlers that should authenticate with the Hub.
|
||||||
|
|
||||||
|
If you are using OAuth, you will also need to register an oauth callback handler to complete the oauth process.
|
||||||
|
A tornado implementation is provided in :class:`HubOAuthCallbackHandler`.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
import base64
|
import base64
|
||||||
@@ -212,6 +226,7 @@ class HubAuth(SingletonConfigurable):
|
|||||||
help="""The base API URL of the Hub.
|
help="""The base API URL of the Hub.
|
||||||
|
|
||||||
Typically `http://hub-ip:hub-port/hub/api`
|
Typically `http://hub-ip:hub-port/hub/api`
|
||||||
|
Default: $JUPYTERHUB_API_URL
|
||||||
""",
|
""",
|
||||||
).tag(config=True)
|
).tag(config=True)
|
||||||
|
|
||||||
@@ -227,7 +242,10 @@ class HubAuth(SingletonConfigurable):
|
|||||||
os.getenv('JUPYTERHUB_API_TOKEN', ''),
|
os.getenv('JUPYTERHUB_API_TOKEN', ''),
|
||||||
help="""API key for accessing Hub API.
|
help="""API key for accessing Hub API.
|
||||||
|
|
||||||
Generate with `jupyterhub token [username]` or add to JupyterHub.services config.
|
Default: $JUPYTERHUB_API_TOKEN
|
||||||
|
|
||||||
|
Loaded from services configuration in jupyterhub_config.
|
||||||
|
Will be auto-generated for hub-managed services.
|
||||||
""",
|
""",
|
||||||
).tag(config=True)
|
).tag(config=True)
|
||||||
|
|
||||||
@@ -236,6 +254,7 @@ class HubAuth(SingletonConfigurable):
|
|||||||
help="""The URL prefix for the Hub itself.
|
help="""The URL prefix for the Hub itself.
|
||||||
|
|
||||||
Typically /hub/
|
Typically /hub/
|
||||||
|
Default: $JUPYTERHUB_BASE_URL
|
||||||
""",
|
""",
|
||||||
).tag(config=True)
|
).tag(config=True)
|
||||||
|
|
||||||
@@ -854,8 +873,6 @@ class HubAuthenticated:
|
|||||||
Examples::
|
Examples::
|
||||||
|
|
||||||
class MyHandler(HubAuthenticated, web.RequestHandler):
|
class MyHandler(HubAuthenticated, web.RequestHandler):
|
||||||
hub_users = {'inara', 'mal'}
|
|
||||||
|
|
||||||
def initialize(self, hub_auth):
|
def initialize(self, hub_auth):
|
||||||
self.hub_auth = hub_auth
|
self.hub_auth = hub_auth
|
||||||
|
|
||||||
@@ -865,6 +882,7 @@ class HubAuthenticated:
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
# deprecated, pre-2.0 allow sets
|
||||||
hub_services = None # set of allowed services
|
hub_services = None # set of allowed services
|
||||||
hub_users = None # set of allowed users
|
hub_users = None # set of allowed users
|
||||||
hub_groups = None # set of allowed groups
|
hub_groups = None # set of allowed groups
|
||||||
@@ -960,6 +978,10 @@ class HubAuthenticated:
|
|||||||
raise UserNotAllowed(model)
|
raise UserNotAllowed(model)
|
||||||
|
|
||||||
# proceed with the pre-2.0 way if hub_scopes is not set
|
# proceed with the pre-2.0 way if hub_scopes is not set
|
||||||
|
warnings.warn(
|
||||||
|
"hub_scopes ($JUPYTERHUB not set, proceeding with pre-2.0 authentication",
|
||||||
|
DeprecationWarning,
|
||||||
|
)
|
||||||
|
|
||||||
if self.allow_admin and model.get('admin', False):
|
if self.allow_admin and model.get('admin', False):
|
||||||
app_log.debug("Allowing Hub admin %s", name)
|
app_log.debug("Allowing Hub admin %s", name)
|
||||||
|
Reference in New Issue
Block a user