mirror of
https://github.com/jupyterhub/jupyterhub.git
synced 2025-10-12 04:23:01 +00:00
update docs for allow_all, allow_existing_users
This commit is contained in:
@@ -37,14 +37,14 @@ A [generic implementation](https://github.com/jupyterhub/oauthenticator/blob/mas
|
||||
## The Dummy Authenticator
|
||||
|
||||
When testing, it may be helpful to use the
|
||||
{class}`jupyterhub.auth.DummyAuthenticator`. This allows for any username and
|
||||
password unless if a global password has been set. Once set, any username will
|
||||
{class}`~.jupyterhub.auth.DummyAuthenticator`. This allows for any username and
|
||||
password unless a global password has been set. Once set, any username will
|
||||
still be accepted but the correct password will need to be provided.
|
||||
|
||||
## Additional Authenticators
|
||||
|
||||
A partial list of other authenticators is available on the
|
||||
[JupyterHub wiki](https://github.com/jupyterhub/jupyterhub/wiki/Authenticators).
|
||||
Additional authenticators can be found on GitHub
|
||||
by searching for [topic:jupyterhub topic:authenticator](https://github.com/search?q=topic%3Ajupyterhub%20topic%3Aauthenticator&type=repositories).
|
||||
|
||||
## Technical Overview of Authentication
|
||||
|
||||
@@ -54,9 +54,9 @@ The base authenticator uses simple username and password authentication.
|
||||
|
||||
The base Authenticator has one central method:
|
||||
|
||||
#### Authenticator.authenticate method
|
||||
#### Authenticator.authenticate
|
||||
|
||||
Authenticator.authenticate(handler, data)
|
||||
{meth}`.Authenticator.authenticate`
|
||||
|
||||
This method is passed the Tornado `RequestHandler` and the `POST data`
|
||||
from JupyterHub's login form. Unless the login form has been customized,
|
||||
@@ -81,7 +81,7 @@ Writing an Authenticator that looks up passwords in a dictionary
|
||||
requires only overriding this one method:
|
||||
|
||||
```python
|
||||
from IPython.utils.traitlets import Dict
|
||||
from traitlets import Dict
|
||||
from jupyterhub.auth import Authenticator
|
||||
|
||||
class DictionaryAuthenticator(Authenticator):
|
||||
@@ -136,7 +136,7 @@ To only allow usernames that start with 'w':
|
||||
c.Authenticator.username_pattern = r'w.*'
|
||||
```
|
||||
|
||||
### How to write a custom authenticator
|
||||
## How to write a custom authenticator
|
||||
|
||||
You can use custom Authenticator subclasses to enable authentication
|
||||
via other mechanisms. One such example is using [GitHub OAuth][].
|
||||
@@ -148,11 +148,6 @@ and {meth}`.Authenticator.post_spawn_stop`, are hooks that can be used to do
|
||||
auth-related startup (e.g. opening PAM sessions) and cleanup
|
||||
(e.g. closing PAM sessions).
|
||||
|
||||
See a list of custom Authenticators [on the wiki](https://github.com/jupyterhub/jupyterhub/wiki/Authenticators).
|
||||
|
||||
If you are interested in writing a custom authenticator, you can read
|
||||
[this tutorial](http://jupyterhub-tutorial.readthedocs.io/en/latest/authenticators.html).
|
||||
|
||||
### Registering custom Authenticators via entry points
|
||||
|
||||
As of JupyterHub 1.0, custom authenticators can register themselves via
|
||||
@@ -188,6 +183,104 @@ Additionally, configurable attributes for your authenticator will
|
||||
appear in jupyterhub help output and auto-generated configuration files
|
||||
via `jupyterhub --generate-config`.
|
||||
|
||||
(authenticator-allow)=
|
||||
|
||||
### Allowing access
|
||||
|
||||
When dealing with logging in, there are generally two _separate_ steps:
|
||||
|
||||
authentication
|
||||
: identifying who is logged in, and
|
||||
|
||||
authorization
|
||||
: deciding whether an authenticated user is logged in
|
||||
|
||||
{meth}`Authenticator.authenticate` is responsible for authenticating users.
|
||||
It is perfectly fine in the simplest cases for `Authenticator.authenticate` to be responsible for authentication _and_ authorization,
|
||||
in which case `authenticate` may return `None` if the user is not authorized.
|
||||
|
||||
However, Authenticators also have have two methods {meth}`~.Authenticator.check_allowed` and {meth}`~.Authenticator.check_blocked_users`, which are called after successful authentication to further check if the user is allowed.
|
||||
|
||||
If `check_blocked_users()` returns False, authorization stops and the user is not allowed.
|
||||
|
||||
If `check_allowed()` returns True, authorization proceeds.
|
||||
|
||||
:::{versionadded} 5.0
|
||||
{attr}`Authenticator.allow_all` and {attr}`Authenticator.allow_existing_users` are new in JupyterHub 5.0.
|
||||
|
||||
By default, `allow_all` is True when `allowed_users` is empty,
|
||||
and `allow_existing_users` is True when `allowed_users` is not empty.
|
||||
This is to ensure backward-compatibility, but subclasses are free to pick more restrictive defaults.
|
||||
:::
|
||||
|
||||
### Overriding `check_allowed`
|
||||
|
||||
The base implementation of {meth}`~.Authenticator.check_allowed` checks:
|
||||
|
||||
- if `allow_all` is True, return True
|
||||
- if username is in the `allowed_users` set, return True
|
||||
- else return False
|
||||
|
||||
If a custom Authenticator defines additional sources of `allow` configuration,
|
||||
such as membership in a group or other information,
|
||||
it should override `check_allowed` to account for this.
|
||||
`allow_` configuration should generally be _additive_,
|
||||
i.e. if permission is granted by _any_ allow configuration,
|
||||
a user should be authorized.
|
||||
|
||||
:::{note}
|
||||
For backward-compatibility, it is the responsibility of `Authenticator.check_allowed()` to check `.allow_all`.
|
||||
This is to avoid the backward-compatible default values from granting permissions unexpectedly.
|
||||
:::
|
||||
|
||||
If an Authenticator defines additional `allow` configuration, it must at least:
|
||||
|
||||
1. override `check_allowed`, and
|
||||
2. override the default for `allow_all`
|
||||
|
||||
The default for `allow_all` in a custom authenticator should be one of `False` or a dynamic default matching something like `if not any allow configuration specified`.
|
||||
False is recommended for authenticators which source much larger pools of users than are _typically_ allowed to access a Hub (e.g. generic OAuth providers like Google, GitHub, etc.).
|
||||
|
||||
For example, here is how `PAMAuthenticator` extends the base class to add `allowed_groups`:
|
||||
|
||||
```python
|
||||
from traitlets import default
|
||||
|
||||
@default("allow_all")
|
||||
def _allow_all_default(self):
|
||||
if self.allowed_users or self.allowed_groups:
|
||||
# if any allow config is specified, default to False
|
||||
return False
|
||||
return True
|
||||
|
||||
def check_allowed(self, username, authentication=None):
|
||||
if self.allow_all:
|
||||
return True
|
||||
if self.check_allowed_groups(username, authentication):
|
||||
return True
|
||||
return super().check_allowed(username, authentication)
|
||||
```
|
||||
|
||||
Important points to note:
|
||||
|
||||
- overriding the default for `allow_all` is required to avoid `allow_all` being True when `allowed_groups` is specified, but `allowed_users` is not.
|
||||
- `allow_all` must be checked inside `check_allowed`
|
||||
- `allowed_groups` strictly expands who is authorized,
|
||||
it does not apply restrictions `allowed_users`.
|
||||
This is recommended for all `allow_` configuration added by Authenticators.
|
||||
|
||||
#### Custom error messages
|
||||
|
||||
Any of these authentication and authorization methods may
|
||||
|
||||
```python
|
||||
from tornado import web
|
||||
|
||||
raise web.HTTPError(403, "informative message")
|
||||
```
|
||||
|
||||
if you want to show a more informative login failure message rather than the generic one.
|
||||
|
||||
(authenticator-auth-state)=
|
||||
|
||||
### Authentication state
|
||||
|
@@ -13,15 +13,25 @@ You can restrict which users are allowed to login with a set,
|
||||
|
||||
```python
|
||||
c.Authenticator.allowed_users = {'mal', 'zoe', 'inara', 'kaylee'}
|
||||
c.Authenticator.allow_all = False
|
||||
c.Authenticator.allow_existing_users = False
|
||||
```
|
||||
|
||||
Users in the `allowed_users` set are added to the Hub database when the Hub is
|
||||
started.
|
||||
Users in the `allowed_users` set are added to the Hub database when the Hub is started.
|
||||
|
||||
```{warning}
|
||||
If this configuration value is not set, then **all authenticated users will be allowed into your hub**.
|
||||
If `allowed_users` is not specified, then by default **all authenticated users will be allowed into your hub**,
|
||||
i.e. `allow_all` defaults to True if neither `allowed_users` nor `allow_all` are set.
|
||||
```
|
||||
|
||||
:::{versionadded} 5.0
|
||||
{attr}`Authenticator.allow_all` and {attr}`Authenticator.allow_existing_users` are new in JupyterHub 5.0.
|
||||
|
||||
By default, `allow_all` is True when `allowed_users` is empty,
|
||||
and `allow_existing_users` is True when `allowed_users` is not empty.
|
||||
This is to ensure backward-compatibility.
|
||||
:::
|
||||
|
||||
## One Time Passwords ( request_otp )
|
||||
|
||||
By setting `request_otp` to true, the login screen will show and additional password input field
|
||||
@@ -42,7 +52,7 @@ c.Authenticator.otp_prompt = 'Google Authenticator:'
|
||||
```{note}
|
||||
As of JupyterHub 2.0, the full permissions of `admin_users`
|
||||
should not be required.
|
||||
Instead, you can assign [roles](define-role-target) to users or groups
|
||||
Instead, it is best to assign [roles](define-role-target) to users or groups
|
||||
with only the scopes they require.
|
||||
```
|
||||
|
||||
@@ -68,26 +78,49 @@ group. For example, we can let any user in the `wheel` group be an admin:
|
||||
c.PAMAuthenticator.admin_groups = {'wheel'}
|
||||
```
|
||||
|
||||
## Give admin access to other users' notebook servers (`admin_access`)
|
||||
## Give some users access to other users' notebook servers
|
||||
|
||||
Since the default `JupyterHub.admin_access` setting is `False`, the admins
|
||||
do not have permission to log in to the single user notebook servers
|
||||
owned by _other users_. If `JupyterHub.admin_access` is set to `True`,
|
||||
then admins have permission to log in _as other users_ on their
|
||||
respective machines for debugging. **As a courtesy, you should make
|
||||
sure your users know if admin_access is enabled.**
|
||||
The `access:servers` scope can be granted to users to give them permission to visit other users' servers.
|
||||
For example, to give members of the `teachers` group access to the servers of members of the `students` group:
|
||||
|
||||
```python
|
||||
c.JupyterHub.load_roles = [
|
||||
{
|
||||
"name": "teachers",
|
||||
"scopes": [
|
||||
"admin-ui",
|
||||
"list:users",
|
||||
"access:servers!group=students",
|
||||
],
|
||||
"groups": ["teachers"],
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
By default, only the deprecated `admin` role has global `access` permissions.
|
||||
**As a courtesy, you should make sure your users know if admin access is enabled.**
|
||||
|
||||
## Add or remove users from the Hub
|
||||
|
||||
Users can be added to and removed from the Hub via the admin
|
||||
panel or the REST API. When a user is **added**, the user will be
|
||||
automatically added to the `allowed_users` set and database. Restarting the Hub
|
||||
will not require manually updating the `allowed_users` set in your config file,
|
||||
panel or the REST API.
|
||||
|
||||
To enable this behavior, set:
|
||||
|
||||
```python
|
||||
c.Authenticator.allow_existing_users = True
|
||||
```
|
||||
|
||||
When a user is **added**, the user will be
|
||||
automatically added to the `allowed_users` set and database.
|
||||
If `allow_existing_users` is True, restarting the Hub will not require manually updating the `allowed_users` set in your config file,
|
||||
as the users will be loaded from the database.
|
||||
If `allow_existing_users` is False, users not granted access by configuration such as `allowed_users` will not be permitted to login,
|
||||
even if they are present in the database.
|
||||
|
||||
After starting the Hub once, it is not sufficient to **remove** a user
|
||||
from the allowed users set in your config file. You must also remove the user
|
||||
from the Hub's database, either by deleting the user from JupyterHub's
|
||||
from the Hub's database, either by deleting the user via JupyterHub's
|
||||
admin page, or you can clear the `jupyterhub.sqlite` database and start
|
||||
fresh.
|
||||
|
||||
|
Reference in New Issue
Block a user