Services Authentication#

Module: jupyterhub.services.auth#

Authenticating services with JupyterHub.

Tokens are sent to the Hub for verification. The Hub replies with a JSON model describing the authenticated user.

This contains two levels of authentication:

  • HubOAuth - Use OAuth 2 to authenticate browsers with the Hub. This should be used for any service that should respond to browser requests (i.e. most services).

  • HubAuth - token-only authentication, for a service that only need to handle token-authenticated API requests

The Auth classes (HubAuth, 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 (HubAuthenticated, 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 HubOAuthCallbackHandler.

HubAuth#

class jupyterhub.services.auth.HubAuth(**kwargs: Any)#

A class for authenticating with JupyterHub

This can be used by any application.

Use this base class only for direct, token-authenticated applications (web APIs). For applications that support direct visits from browsers, use HubOAuth to enable OAuth redirect-based authentication.

If using tornado, use via HubAuthenticated mixin. If using manually, use the .user_for_token(token_value) method to identify the user owning a given token.

The following config must be set:

  • api_token (token for authenticating with JupyterHub API), fetched from the JUPYTERHUB_API_TOKEN env by default.

The following config MAY be set:

  • api_url: the base URL of the Hub’s internal API, fetched from JUPYTERHUB_API_URL by default.

  • cookie_cache_max_age: the number of seconds responses from the Hub should be cached.

  • login_url (the public /hub/login URL of the Hub).

access_scopes c.HubAuth.access_scopes = Set()#

OAuth scopes to use for allowing access.

Get from $JUPYTERHUB_OAUTH_ACCESS_SCOPES by default.

allow_token_in_url c.HubAuth.allow_token_in_url = Bool(False)#

Allow requests to pages with ?token=… in the URL

This allows starting a user session by sharing a URL with credentials, bypassing authentication with the Hub.

If False, tokens in URLs will be ignored by the server, except on websocket requests.

Has no effect on websocket requests, which can only reliably authenticate via token in the URL, as recommended by browser Websocket implementations.

This will default to False in JupyterHub 5.

Added in version 4.1.

Changed in version 5.0: default changed to False

Allow websocket requests with only cookie for authentication

Cookie-authenticated websockets cannot be protected from other user servers unless per-user domains are used. Disabling cookie auth on websockets protects user servers from each other, but may break some user applications. Per-user domains eliminate the need to lock this down.

JupyterLab 4.1.2 and Notebook 6.5.6, 7.1.0 will not work because they rely on cookie authentication without API or XSRF tokens.

Added in version 4.1.

api_token c.HubAuth.api_token = Unicode('')#

API key for accessing Hub API.

Default: $JUPYTERHUB_API_TOKEN

Loaded from services configuration in jupyterhub_config. Will be auto-generated for hub-managed services.

api_url c.HubAuth.api_url = Unicode('http://127.0.0.1:8081/hub/api')#

The base API URL of the Hub.

Typically http://hub-ip:hub-port/hub/api Default: $JUPYTERHUB_API_URL

base_url c.HubAuth.base_url = Unicode('/')#

The base URL prefix of this application

e.g. /services/service-name/ or /user/name/

Default: get from JUPYTERHUB_SERVICE_PREFIX

cache_max_age c.HubAuth.cache_max_age = Int(300)#

The maximum time (in seconds) to cache the Hub’s responses for authentication.

A larger value reduces load on the Hub and occasional response lag. A smaller value reduces propagation time of changes on the Hub (rare).

Default: 300 (five minutes)

certfile c.HubAuth.certfile = Unicode('')#

The ssl cert to use for requests

Use with keyfile

check_scopes(required_scopes, user)#

Check whether the user has required scope(s)

client_ca c.HubAuth.client_ca = Unicode('')#

The ssl certificate authority to use to verify requests

Use with keyfile and certfile

cookie_cache_max_age Int(0)#

DEPRECATED. Use cache_max_age

cookie_host_prefix_enabled c.HubAuth.cookie_host_prefix_enabled = Bool(False)#

Enable __Host- prefix on authentication cookies.

The __Host- prefix on JupyterHub cookies provides further protection against cookie tossing when untrusted servers may control subdomains of your jupyterhub deployment.

_However_, it also requires that cookies be set on the path /, which means they are shared by all JupyterHub components, so a compromised server component will have access to _all_ JupyterHub-related cookies of the visiting browser. It is recommended to only combine __Host- cookies with per-user domains.

Set via $JUPYTERHUB_COOKIE_HOST_PREFIX_ENABLED

cookie_options c.HubAuth.cookie_options = Dict()#

Additional options to pass when setting cookies.

Can include things like expires_days=None for session-expiry or secure=True if served on HTTPS and default HTTPS discovery fails (e.g. behind some proxies).

property cookie_path#

Path prefix on which to set cookies

self.base_url, but ‘/’ when cookie_host_prefix_enabled is True

get_session_id(handler)#

Get the jupyterhub session id

from the jupyterhub-session-id cookie.

Parameters:

handler (tornado.web.RequestHandler) – the current request handler

get_token(handler, in_cookie=True)#

Get the token authenticating a request

Changed in version 2.2: in_cookie added. Previously, only URL params and header were considered. Pass in_cookie=False to preserve that behavior.

  • in URL parameters: ?token=<token>

  • in header: Authorization: token <token>

  • in cookie (stored after oauth), if in_cookie is True

Parameters:

handler (tornado.web.RequestHandler) – the current request handler

get_user(handler, *, sync=True)#

Get the Hub user for a given tornado handler.

Checks cookie with the Hub to identify the current user.

Added in version 2.4: async support via sync argument.

Parameters:
Returns:

The user model, if a user is identified, None if authentication fails.

The ‘name’ field contains the user’s name.

Return type:

user_model (dict)

hub_host c.HubAuth.hub_host = Unicode('')#

The public host of JupyterHub

Only used if JupyterHub is spreading servers across subdomains.

hub_prefix c.HubAuth.hub_prefix = Unicode('/hub/')#

The URL prefix for the Hub itself.

Typically /hub/ Default: $JUPYTERHUB_BASE_URL

keyfile c.HubAuth.keyfile = Unicode('')#

The ssl key to use for requests

Use with certfile

login_url c.HubAuth.login_url = Unicode('/hub/login')#

The login URL to use

Typically /hub/login

Deprecated and removed. Use HubOAuth to authenticate browsers.

user_for_token(token, use_cache=True, session_id='', *, sync=True)#

Ask the Hub to identify the user for a given token.

Added in version 2.4: async support via sync argument.

Parameters:
  • token (str) – the token

  • use_cache (bool) – Specify use_cache=False to skip cached cookie values (default: True)

  • sync (bool) – whether to block for the result or return an awaitable

Returns:

The user model, if a user is identified, None if authentication fails.

The ‘name’ field contains the user’s name.

Return type:

user_model (dict)

HubOAuth#

class jupyterhub.services.auth.HubOAuth(**kwargs: Any)#

HubAuth using OAuth for login instead of cookies set by the Hub.

Use this class if you want users to be able to visit your service with a browser. They will be authenticated via OAuth with the Hub.

access_scopes c.HubOAuth.access_scopes = Set()#

OAuth scopes to use for allowing access.

Get from $JUPYTERHUB_OAUTH_ACCESS_SCOPES by default.

allow_token_in_url c.HubOAuth.allow_token_in_url = Bool(False)#

Allow requests to pages with ?token=… in the URL

This allows starting a user session by sharing a URL with credentials, bypassing authentication with the Hub.

If False, tokens in URLs will be ignored by the server, except on websocket requests.

Has no effect on websocket requests, which can only reliably authenticate via token in the URL, as recommended by browser Websocket implementations.

This will default to False in JupyterHub 5.

Added in version 4.1.

Changed in version 5.0: default changed to False

Allow websocket requests with only cookie for authentication

Cookie-authenticated websockets cannot be protected from other user servers unless per-user domains are used. Disabling cookie auth on websockets protects user servers from each other, but may break some user applications. Per-user domains eliminate the need to lock this down.

JupyterLab 4.1.2 and Notebook 6.5.6, 7.1.0 will not work because they rely on cookie authentication without API or XSRF tokens.

Added in version 4.1.

api_token c.HubOAuth.api_token = Unicode('')#

API key for accessing Hub API.

Default: $JUPYTERHUB_API_TOKEN

Loaded from services configuration in jupyterhub_config. Will be auto-generated for hub-managed services.

api_url c.HubOAuth.api_url = Unicode('http://127.0.0.1:8081/hub/api')#

The base API URL of the Hub.

Typically http://hub-ip:hub-port/hub/api Default: $JUPYTERHUB_API_URL

base_url c.HubOAuth.base_url = Unicode('/')#

The base URL prefix of this application

e.g. /services/service-name/ or /user/name/

Default: get from JUPYTERHUB_SERVICE_PREFIX

cache_max_age c.HubOAuth.cache_max_age = Int(300)#

The maximum time (in seconds) to cache the Hub’s responses for authentication.

A larger value reduces load on the Hub and occasional response lag. A smaller value reduces propagation time of changes on the Hub (rare).

Default: 300 (five minutes)

certfile c.HubOAuth.certfile = Unicode('')#

The ssl cert to use for requests

Use with keyfile

check_xsrf_cookie patch

Applies JupyterHub check_xsrf_cookie if not token authenticated

Clear the OAuth cookie

Parameters:

handler (tornado.web.RequestHandler) – the current request handler

clear_oauth_state(state_id)#

Clear persisted oauth state

clear_oauth_state_cookies(handler)#

Clear persisted oauth state

client_ca c.HubOAuth.client_ca = Unicode('')#

The ssl certificate authority to use to verify requests

Use with keyfile and certfile

cookie_host_prefix_enabled c.HubOAuth.cookie_host_prefix_enabled = Bool(False)#

Enable __Host- prefix on authentication cookies.

The __Host- prefix on JupyterHub cookies provides further protection against cookie tossing when untrusted servers may control subdomains of your jupyterhub deployment.

_However_, it also requires that cookies be set on the path /, which means they are shared by all JupyterHub components, so a compromised server component will have access to _all_ JupyterHub-related cookies of the visiting browser. It is recommended to only combine __Host- cookies with per-user domains.

Set via $JUPYTERHUB_COOKIE_HOST_PREFIX_ENABLED

property cookie_name#

Use OAuth client_id for cookie name

because we don’t want to use the same cookie name across OAuth clients.

cookie_options c.HubOAuth.cookie_options = Dict()#

Additional options to pass when setting cookies.

Can include things like expires_days=None for session-expiry or secure=True if served on HTTPS and default HTTPS discovery fails (e.g. behind some proxies).

generate_state(next_url=None, **extra_state)#

Generate a state string, given a next_url redirect target

The state info is stored locally in self._oauth_states, and only the state id is returned for use in the oauth state field (cookie, redirect param)

Parameters:

next_url (str) – The URL of the page to redirect to on successful login.

Returns:

state_id (str)

Return type:

The state string to be used as a cookie value.

get_next_url(state_id='', /)#

Get the next_url for redirection, given an encoded OAuth state

Get the cookie name for oauth state, given an encoded OAuth state

Cookie name is stored in the state itself because the cookie name is randomized to deal with races between concurrent oauth sequences.

hub_host c.HubOAuth.hub_host = Unicode('')#

The public host of JupyterHub

Only used if JupyterHub is spreading servers across subdomains.

hub_prefix c.HubOAuth.hub_prefix = Unicode('/hub/')#

The URL prefix for the Hub itself.

Typically /hub/ Default: $JUPYTERHUB_BASE_URL

keyfile c.HubOAuth.keyfile = Unicode('')#

The ssl key to use for requests

Use with certfile

login_url c.HubOAuth.login_url = Unicode('/hub/login')#

The login URL to use

Typically /hub/login

oauth_authorization_url c.HubOAuth.oauth_authorization_url = Unicode('/hub/api/oauth2/authorize')#

The URL to redirect to when starting the OAuth process

oauth_client_id c.HubOAuth.oauth_client_id = Unicode('')#

The OAuth client ID for this application.

Use JUPYTERHUB_CLIENT_ID by default.

oauth_redirect_uri c.HubOAuth.oauth_redirect_uri = Unicode('')#

OAuth redirect URI

Should generally be /base_url/oauth_callback

oauth_state_max_age c.HubOAuth.oauth_state_max_age = Int(600)#

Max age (seconds) of oauth state.

Governs both oauth state cookie Max-Age, as well as the in-memory _oauth_states cache.

oauth_token_url c.HubOAuth.oauth_token_url = Unicode('')#

The URL for requesting an OAuth token from JupyterHub

Set a cookie recording OAuth result

Generate an OAuth state and store it in a cookie

Parameters:
  • handler (RequestHandler) – A tornado RequestHandler

  • next_url (str) – The page to redirect to on successful login

Returns:

state – The OAuth state that has been stored in the cookie (url safe, base64-encoded)

Return type:

str

The cookie name for storing OAuth state

This cookie is only live for the duration of the OAuth handshake.

token_for_code(code, *, sync=True)#

Get token for OAuth temporary code

This is the last step of OAuth login. Should be called in OAuth Callback handler.

Parameters:

code (str) – oauth code for finishing OAuth login

Returns:

JupyterHub API Token

Return type:

token (str)

HubAuthenticated#

class jupyterhub.services.auth.HubAuthenticated#

Mixin for tornado handlers that are authenticated with JupyterHub

A handler that mixes this in must have the following attributes/properties:

  • .hub_auth: A HubAuth instance

  • .hub_scopes: A set of JupyterHub 2.0 OAuth scopes to allow. Default comes from .hub_auth.oauth_access_scopes, which in turn is set by $JUPYTERHUB_OAUTH_ACCESS_SCOPES Default values include: - ‘access:services’, ‘access:services!service={service_name}’ for services - ‘access:servers’, ‘access:servers!user={user}’, ‘access:servers!server={user}/{server_name}’ for single-user servers

If hub_scopes is not used (e.g. JupyterHub 1.x), these additional properties can be used:

  • .allow_admin: If True, allow any admin user. Default: False.

  • .hub_users: A set of usernames to allow. If left unspecified or None, username will not be checked.

  • .hub_groups: A set of group names to allow. If left unspecified or None, groups will not be checked.

  • .allow_admin: Is admin user access allowed or not If left unspecified or False, admin user won’t have an access.

Examples:

class MyHandler(HubAuthenticated, web.RequestHandler):
    def initialize(self, hub_auth):
        self.hub_auth = hub_auth

    @web.authenticated
    def get(self):
        ...
property allow_all#

Property indicating that all successfully identified user or service should be allowed.

check_hub_user(model)#

Check whether Hub-authenticated user or service should be allowed.

Returns the input if the user should be allowed, None otherwise.

Override for custom logic in authenticating users.

Parameters:

user_model (dict) – the user or service model returned from HubAuth

Returns:

The user model if the user should be allowed, None otherwise.

Return type:

user_model (dict)

get_current_user()#

Tornado’s authentication method

Returns:

The user model, if a user is identified, None if authentication fails.

Return type:

user_model (dict)

get_login_url()#

Return the Hub’s login URL

hub_auth_class#

alias of HubAuth

property hub_scopes#

Set of allowed scopes (use hub_auth.access_scopes by default)

HubOAuthenticated#

class jupyterhub.services.auth.HubOAuthenticated#

Simple subclass of HubAuthenticated using OAuth instead of old shared cookies

HubOAuthCallbackHandler#

class jupyterhub.services.auth.HubOAuthCallbackHandler(application: Application, request: HTTPServerRequest, **kwargs: Any)#

OAuth Callback handler

Finishes the OAuth flow, setting a cookie to record the user’s info.

Should be registered at SERVICE_PREFIX/oauth_callback