TODO:
Steps
OAuth + JupyterHub Authenticator = OAuthenticator
OAuthenticator currently supports the following authentication services:
A generic implementation <oauthenticator.generic.GenericOAuthenticator>, which you can use with any provider, is also available.
For an example docker image using OAuthenticator, see the examples directory.
Another example is using GitHub OAuth to spawn each user’s server in a separate docker container.
Install with pip:
pip3 install oauthenticator
Or clone the repo and do a dev install:
git clone https://github.com/jupyterhub/oauthenticator.git cd oauthenticator pip3 install -e .
The first step is to tell JupyterHub to use your chosen OAuthenticator. Each authenticator is provided in a submodule of oauthenticator, and each authenticator has a variant with Local (e.g. LocalGitHubOAuthenticator), which will map OAuth usernames onto local system usernames.
oauthenticator
Local
LocalGitHubOAuthenticator
In jupyterhub_config.py, add:
jupyterhub_config.py
from oauthenticator.github import GitHubOAuthenticator c.JupyterHub.authenticator_class = GitHubOAuthenticator
All OAuthenticators require setting a callback URL, client ID, and client secret. You will generally get these when you register your OAuth application with your OAuth provider. Provider-specific details are available in sections below. When registering your oauth application with your provider, you will probably need to specify a callback URL. The callback URL should look like:
http[s]://[your-host]/hub/oauth_callback
where [your-host] is where your server will be running. Such as example.com:8000.
[your-host]
example.com:8000
When JupyterHub runs, these values will be retrieved from the environment variables:
$OAUTH_CALLBACK_URL $OAUTH_CLIENT_ID $OAUTH_CLIENT_SECRET
You can also set these values in your configuration file, jupyterhub_config.py:
# Replace MyOAuthenticator with your selected OAuthenticator class (e.g. c.GithubOAuthenticator). c.MyOAuthenticator.oauth_callback_url = 'http[s]://[your-host]/hub/oauth_callback' c.MyOAuthenticator.client_id = 'your-client-id' c.MyOAuthenticator.client_secret = 'your-client-secret'
> pip3 install PyJWT
> export AAD_TENANT_ID='{AAD-TENANT-ID}'
examples > azuread > sample_jupyter_config.py
'{}'
Follow this link to create an AAD APP
Application ID
Azure portal --> AD --> App Registrations --> App
Directory ID
Azure portal --> AD --> Properties
jupyterhub_config.py:
import os from oauthenticator.azuread import AzureAdOAuthenticator c.JupyterHub.authenticator_class = AzureAdOAuthenticator c.Application.log_level = 'DEBUG' c.AzureAdOAuthenticator.tenant_id = os.environ.get('AAD_TENANT_ID') c.AzureAdOAuthenticator.oauth_callback_url = 'http://{your-domain}/hub/oauth_callback' c.AzureAdOAuthenticator.client_id = '{AAD-APP-CLIENT-ID}' c.AzureAdOAuthenticator.client_secret = '{AAD-APP-CLIENT-SECRET}'
sudo jupyterhub -f ./path/to/jupyterhub_config.py
See run.sh for an example
run.sh
> export OAUTH_ACCESS_TOKEN_URL='https://login.microsoftonline.com/YOUR_TENANT.onmicrosoft.com/oauth2/v2.0/token?p=YOUR_POLICY_NAME' > export OAUTH_AUTHORIZE_URL='https://login.microsoftonline.com/YOUR_TENANT.onmicrosoft.com/oauth2/v2.0/authorize?p=YOUR_POLICY_NAME' > export OAUTH_SCOPE='openid YOUR_RESOURCE'
The sample code can be found at examples folder * See run.sh for setting up environment variables. * See config.py for setting up such as client id/secret and add_user_cmd.
config.py
The source code can be found at here.
First, you’ll need to create a GitHub OAuth application.
Then, add the following to your jupyterhub_config.py file:
You can also use LocalGitHubOAuthenticator to map GitHub accounts onto local users.
You can use your own Github Enterprise instance by setting the GITHUB_HOST environment variable.
GITHUB_HOST
You can set GITHUB_HTTP environment variable to true or anything if your GitHub Enterprise supports http only.
GITHUB_HTTP
GitHub allows expanded capabilities by adding GitHub-Specific Scopes to the requested token.
First, you’ll need to create a GitLab OAuth application.
from oauthenticator.gitlab import GitLabOAuthenticator c.JupyterHub.authenticator_class = GitLabOAuthenticator
You can also use LocalGitLabOAuthenticator to map GitLab accounts onto local users.
LocalGitLabOAuthenticator
You can use your own GitLab CE/EE instance by setting the GITLAB_HOST environment flag.
GITLAB_HOST
You can restrict access to only accept members of certain projects or groups by setting
c.GitLabOAuthenticator.gitlab_project_id_whitelist = [ ... ]
and
c.GitLabOAuthenticator.gitlab_group_whitelist = [ ... ]
but be aware that each entry incurs a separate API call, increasing the risk of rate limiting and timeouts.
Visit https://console.developers.google.com to set up an OAuth client ID and secret. See Google’s documentation on how to create OAUth 2.0 client credentials. The Authorized JavaScript origins should be set to to your hub’s public address while Authorized redirect URIs should be set to the same but followed by /hub/oauth_callback.
Authorized JavaScript origins
Authorized redirect URIs
/hub/oauth_callback
from oauthenticator.google import GoogleOAuthenticator c.JupyterHub.authenticator_class = GoogleOAuthenticator
By default, any domain is allowed to login but you can restrict authorized domains with a list (recommended):
c.GoogleOAuthenticator.hosted_domain = ['mycollege.edu', 'mycompany.com']
You can customize the sign in button text (optional):
c.GoogleOAuthenticator.login_service = 'My College'
In case you have an OpenShift deployment with OAuth properly configured (see the following sections for a quick reference), you should set the client ID and secret by the environment variables OAUTH_CLIENT_ID, OAUTH_CLIENT_SECRET and OAUTH_CALLBACK_URL.
OAUTH_CLIENT_ID
OAUTH_CLIENT_SECRET
OAUTH_CALLBACK_URL
Prior to OpenShift 4.0, the OAuth provider and REST API URL endpoints can be specified by setting the single environment variable OPENSHIFT_URL. From OpenShift 4.0 onwards, these two endpoints are on different hosts. You need to set OPENSHIFT_AUTH_API_URL to the OAuth provider URL, and OPENSHIFT_REST_API_URL to the REST API URL endpoint.
OPENSHIFT_URL
OPENSHIFT_AUTH_API_URL
OPENSHIFT_REST_API_URL
The OAUTH_CALLBACK_URL should match http[s]://[your-app-route]/hub/oauth_callback
http[s]://[your-app-route]/hub/oauth_callback
As a cluster admin, you can create a global OAuth client in your OpenShift cluster creating a new OAuthClient object using the API:
$ oc create -f - <<EOF apiVersion: v1 kind: OAuthClient metadata: name: <OAUTH_CLIENT_ID> redirectURIs: - <OUAUTH_CALLBACK_URL> secret: <OAUTH_SECRET> EOF
As a project member, you can use the Service Accounts as OAuth Clients scenario. This gives you the possibility of defining clients associated with service accounts. You just need to create the service account with the proper annotations:
$ oc create -f - <<EOF apiVersion: v1 kind: ServiceAccount metadata: name: <name> annotations: serviceaccounts.openshift.io/oauth-redirecturi.1: '<OUAUTH_CALLBACK_URL>' EOF
In this scenario your OAUTH_CLIENT_ID will be system:serviceaccount:<serviceaccount_namespace>:<serviceaccount_name>, the OAUTH_CLIENT_SECRET is the API token of the service account (oc sa get-token <serviceaccount_name>) and the OAUTH_CALLBACK_URL is the value of the annotation serviceaccounts.openshift.io/oauth-redirecturi.1. More details can be found in the upstream documentation.
system:serviceaccount:<serviceaccount_namespace>:<serviceaccount_name>
oc sa get-token <serviceaccount_name>
serviceaccounts.openshift.io/oauth-redirecturi.1
Okpy is an auto-grading tool that is widely used in UC Berkeley EECS and Data Science courses. This authenticator enhances its support for Jupyter Notebook by enabling students to authenticate with the Hub first and saving relevant user states to the env (the feature is redacted until a secure state saving mechanism is developed).
env
If you want to authenticate your Hub using OkpyAuthenticator, you need to specify the authenticator class in your jupyterhub_config.py file:
from oauthenticator.okpy import OkpyOAuthenticator c.JupyterHub.authenticator_class = OkpyOAuthenticator
and set your OAUTH_ environment variables.
OAUTH_
Visit https://developers.globus.org/ to set up your app. Ensure Native App is unchecked and make sure the callback URL looks like:
https://[your-host]/hub/oauth_callback
Set scopes for authorization and transfer. The defaults include:
openid profile urn:globus:auth:scope:transfer.api.globus.org:all
Set the above settings in your jupyterhub_config:
jupyterhub_config
# Tell JupyterHub to create system accounts from oauthenticator.globus import LocalGlobusOAuthenticator c.JupyterHub.authenticator_class = LocalGlobusOAuthenticator c.LocalGlobusOAuthenticator.enable_auth_state = True c.LocalGlobusOAuthenticator.oauth_callback_url = 'https://[your-host]/hub/oauth_callback' c.LocalGlobusOAuthenticator.client_id = '[your app client id]' c.LocalGlobusOAuthenticator.client_secret = '[your app client secret]'
Alternatively you can set env variables for the following: OAUTH_CALLBACK_URL, OAUTH_CLIENT_ID, and OAUTH_CLIENT_SECRET. Setting JUPYTERHUB_CRYPT_KEY is required, and can be generated with OpenSSL: openssl rand -hex 32
JUPYTERHUB_CRYPT_KEY
openssl rand -hex 32
You are all set by this point! Be sure to check below for tweaking settings related to User Identity, Transfer, and additional security.
By default, all users are restricted to their Globus IDs (example@globusid.org) with the default Jupyterhub config:
c.GlobusOAuthenticator.identity_provider = 'globusid.org'
If you want to use a Linked Identity such as malcolm@universityofindependence.edu, go to your App Developer page and set Required Identity Provider for your app to <Your University>, and set the following in the config:
malcolm@universityofindependence.edu
<Your University>
c.GlobusOAuthenticator.identity_provider = 'universityofindependence.edu'
The default configuration will automatically setup user environments with tokens, allowing them to start up python notebooks and initiate Globus Transfers. If you want to transfer data onto your JupyterHub server, it’s suggested you install Globus Connect Server and add the globus_local_endpoint uuid below. If you want to change other behavior, you can modify the defaults below:
globus_local_endpoint
# Allow Refresh Tokens in user notebooks. Disallow these for increased security, # allow them for better usability. c.LocalGlobusOAuthenticator.allow_refresh_tokens = True # Default scopes are below if unspecified. Add a custom transfer server if you have one. c.LocalGlobusOAuthenticator.scope = ['openid', 'profile', 'urn:globus:auth:scope:transfer.api.globus.org:all'] # Default tokens excluded from being passed into the spawner environment c.LocalGlobusOAuthenticator.exclude_tokens = ['auth.globus.org'] # If the JupyterHub server is an endpoint, for convenience the endpoint id can be # set here. It will show up in the notebook kernel for all users as 'GLOBUS_LOCAL_ENDPOINT'. c.LocalGlobusOAuthenticator.globus_local_endpoint = '<Your Local JupyterHub UUID>' # Set a custom logout URL for your identity provider c.LocalGlobusOAuthenticator.logout_redirect_url = 'https://auth.globus.org/v2/web/logout' # For added security, revoke all service tokens when users logout. (Note: users must start # a new server to get fresh tokens, logging out does not shut it down by default) c.LocalGlobusOAuthenticator.revoke_tokens_on_logout = False
If you only want to authenticate users with their Globus IDs but don’t want to allow them to do transfers, you can remove urn:globus:auth:scope:transfer.api.globus.org:all. Conversely, you can add an additional scope for another transfer server if you wish.
urn:globus:auth:scope:transfer.api.globus.org:all
Use c.GlobusOAuthenticator.exclude to prevent tokens from being passed into a users environment. By default, auth.globus.org is excluded but transfer.api.globus.org is allowed. If you want to disable transfers, modify c.GlobusOAuthenticator.scope instead of c.GlobusOAuthenticator.exclude to avoid procuring unnecessary tokens.
c.GlobusOAuthenticator.exclude
auth.globus.org
transfer.api.globus.org
c.GlobusOAuthenticator.scope
First install the OAuth2 Server Plugin for Moodle.
Use the GenericOAuthenticator for Jupyterhub by editing your jupyterhub_config.py accordingly:
GenericOAuthenticator
from oauthenticator.generic import GenericOAuthenticator c.JupyterHub.authenticator_class = GenericOAuthenticator c.GenericOAuthenticator.oauth_callback_url = 'http://YOUR-JUPYTERHUB.com/hub/oauth_callback' c.GenericOAuthenticator.client_id = 'MOODLE-CLIENT-ID' c.GenericOAuthenticator.client_secret = 'MOODLE-CLIENT-SECRET-KEY' c.GenericOAuthenticator.login_service = 'NAME-OF-SERVICE' c.GenericOAuthenticator.userdata_url = 'http://YOUR-MOODLE-DOMAIN.com/local/oauth/user_info.php' c.GenericOAuthenticator.token_url = 'http://YOUR-MOODLE-DOMAIN.com/local/oauth/token.php' c.GenericOAuthenticator.userdata_method = 'POST' c.GenericOAuthenticator.extra_params = { 'scope': 'user_info', 'client_id': 'MOODLE-CLIENT-ID', 'client_secret': 'MOODLE-CLIENT-SECRET-KEY'}
And set your environmental variable OAUTH2_AUTHORIZE_URL to:
OAUTH2_AUTHORIZE_URL
http://YOUR-MOODLE-DOMAIN.com/local/oauth/login.php?client_id=MOODLE-CLIENT-ID&response_type=code
First visit Yandex OAuth to setup your app. Ensure that Web services is checked (in the Platform section) and make sure the Callback URI #1 looks like:
Choose Yandex.Passport API in Permissions and check these options:
Set the above settings in your jupyterhub_config.py:
```python c.JupyterHub.authenticator_class = ‘oauthenticator.yandex.YandexPassportOAuthenticator’ c.YandexPassportOAuthenticator.oauth_callback_url = ‘https://[your-host]/hub/oauth_callback’ c.YandexPassportOAuthenticator.client_id = ‘[your app ID]’ c.YandexPassportOAuthenticator.client_secret = ‘[your app Password]’