Authentication and authorization

Authentication is about identity, while authorization is about permissions. In this section you will learn how to configure both. As an example, you can configure authentication using GitHub accounts and restrict what users are authorized based on membership of a GitHub organization.

Before configuring this, you should have setup HTTPS.

Useful understanding

Authenticator classes

JupyterHub by default ships with only one source of authentication: PAM, the underlying unix authentication of the host system. To use other sources of authentication, choose one authenticator class to use. Several such classes are already available in the hub image through installed Python packages.

JupyterHub provides a base class, Authenticator, that all other authenticator classes are supposed to derive from. By configuring this base class, we influence the behavior of the derived class as well.

The configuration system

We configure JupyterHub to use our chosen authenticator class and the authenticator class itself through this Helm chart’s hub.config configuration.

General configuration

As all authenticator classes derive from the Authenticator base class, they share some configuration options. Below are some common configuration options, but please refer to the official configuration reference for more details.

allowed_users / admin_users

Some authenticator classes may have dedicated logic in addition this this to authorize users.

hub:
  config:
    Authenticator:
      admin_users:
        - user1
        - user2
      allowed_users:
        - user3
        - user4
    # ...
    DummyAuthenticator:
      password: a-shared-secret-password
    JupyterHub:
      authenticator_class: dummy

In the above configuration, we have configured three things:

  1. JupyterHub is instructed to use the dummy authenticator to login (only appropriate for testing purposes),

  2. anyone will be able to login with username user1-4 and the password a-shared-secret-password

  3. user1 and user2 will have admin permissions, while user3 and user4 will be regular users.

auto_login

If you have configured authentication with GitHub for example, the page /hub/login will feature a single orange button that users are to press to login. If you want to bypass this screen and send users directly to GitHub login, you can set auto_login to true.

hub:
  config:
    Authenticator:
      auto_login: true

enable_auth_state

If you want JupyterHub to persist often sensitive information received as part of logging in, you need to enable it.

hub:
  config:
    Authenticator:
      enable_auth_state: true

For more information about authentication state, see JupyterHub’s own documentation about authentication state.

Note

The encryption and decryption of auth state requires a cryptographical key.

As of version 1.0.0 this will automatically be generated and there is no need to set it manually.

If you wish to reset a generated key, you can use kubectl edit on the k8s Secret typically named hub and remove the hub.config.CryptKeeper.keys entry in the k8s Secret, then perform a new helm upgrade.

To manually set a cryptographical key, you can do it like this.

hub:
  config:
    CryptKeeper:
      keys:
        - 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef

Configuring authenticator classes

Below we provide a few configuration examples of commonly used authentication classes. For more details about them, please see the authentication class’ own documentation.

OAuth2 based authentication

JupyterHub’s oauthenticator has support for enabling your users to authenticate via a third-party OAuth2 identity provider such as GitHub, Google, and CILogon. All of these will require an OAuth2 client id and client secret.

For details on how to acquire a client id and client secret, please refer to oauthenticator’s documentation.

GitHub

GitHub is the largest hosting service for git repositories. It is free to create an account at GitHub, and relatively straightforward to set up OAuth credentials so that users can authenticate with their GitHub username/password.

To create OAuth credentials on GitHub, follow these steps:

  • Click your profile picture -> settings -> developer settings

  • Make sure you’re on the “OAuth Apps” tab, then click “New OAuth App”

  • Fill out the forms (you’ll need your hub address) and generate your ID/Secret.

To enable GitHub authentication, your config.yaml should contain the following configuration:

hub:
  config:
    GitHubOAuthenticator:
      client_id: your-client-id
      client_secret: your-client-secret
      oauth_callback_url: https://your-jupyterhub-domain/hub/oauth_callback
    JupyterHub:
      authenticator_class: github

Make sure that the oauth_callback_url matches the one you set in GitHub.

To restrict access to the members of one or more GitHub organizations, amend your previous configuration with these parts.

hub:
  config:
    GitHubOAuthenticator:
      allowed_organizations:
        - my-github-organization
      scope:
        - read:user

Alternative scopes

While you can set other scopes than read:user as described in GitHub OAuth scopes documentation, we recommend read:user.

With read:user, the user will be requested to permit JupyterHub to read their profile data. The benefit of this choice is that it won’t require configuration by the GitHub organizations’ admins by by its members.

Google

Google authentication is used by many universities (it is part of “G Suite”).

If your institution is a G Suite customer that integrates with Google services such as Gmail, Calendar, and Drive, you can authenticate users to your JupyterHub using Google for authentication.

  1. Log in to the Google API Console.

  2. Select a project > Create a project… and set ‘Project name’. This is a short term that is only displayed in the console. If you have already created a project you may skip this step.

  3. Type “Credentials” in the search field at the top and click to access the Credentials API.

  4. Click “Create credentials”, then “OAuth client ID”. Choose “Application type” > “Web application”.

  5. Enter a name for your JupyterHub instance. You can give it a descriptive name or set it to be the hub’s hostname.

  6. Set “Authorized JavaScript origins” to be your hub’s URL.

  7. Set “Authorized redirect URIs” to be your hub’s URL followed by /hub/oauth_callback. For example, https://your-jupyterhub-domain/hub/oauth_callback.

  8. When you click “Create”, the console will generate and display a Client ID and Client Secret. Save these values.

  9. Type “consent screen” in the search field at the top and click to access the OAuth consent screen. Here you will customize what your users see when they login to your JupyterHub instance for the first time. Click Save when you are done.

  10. Update your Helm chart’s configuration (config.yaml) to look like this.

hub:
  config:
    GoogleOAuthenticator:
      client_id: your-client-id.apps.googleusercontent.com
      client_secret: your-client-secret
      oauth_callback_url: https://your-jupyterhub-domain/hub/oauth_callback
      hosted_domain:
        - your-university.edu
      login_service: Your university
    JupyterHub:
      authenticator_class: google

The oauth_callback_url key is set to the authorized redirect URI you specified earlier. Set hosted_domain to your institution’s domain name. The value of login_service is a descriptive term for your institution that reminds your users which account they are using to login.

CILogon

Please see CyberInfrastructure Logon’s website for more information about what kind of identity is managed by CILogon.

hub:
  config:
    CILogonOAuthenticator:
      client_id: your-client-id
      client_secret: your-client-secret
      oauth_callback_url: https://your-jupyterhub-domain/hub/oauth_callback
    JupyterHub:
      authenticator_class: cilogon

Based on this caveat, you may need to also set the following.

hub:
  config:
    CILogonOAuthenticator:
      username_claim: email

Globus

Globus Auth is a foundational identity and access management platform service designed to address unique needs of the science and engineering community. Globus provides cloud-based services for reliably moving, sharing, publishing and discovering data, whether your files live on a supercomputer, lab cluster, tape archive, public cloud, or your own laptop. Start a Globus app here!

hub:
  config:
    GlobusOAuthenticator:
      client_id: your-client-id
      client_secret: your-client-secret
      oauth_callback_url: https://your-jupyterhub-domain/hub/oauth_callback
      identity_provider: your-university.edu
    JupyterHub:
      authenticator_class: globus

Azure Active Directory

Azure Active Directory is an identity provider from Microsoft Azure. Apart from needing a OAuth2 client id and client secret, you will also need a tenant id.

hub:
  config:
    AzureAdOAuthenticator:
      client_id: your-client-id
      client_secret: your-client-secret
      oauth_callback_url: https://your-jupyterhub-domain/hub/oauth_callback
      tenant_id: your-tenant-id
    JupyterHub:
      authenticator_class: azuread

Auth0

Auth0 is a commercial provider of identity management.

hub:
  config:
    Auth0OAuthenticator:
      client_id: client-id-from-auth0-here
      client_secret: client-secret-from-auth0-here
      oauth_callback_url: https://your-jupyterhub-domain/hub/oauth_callback
      scope:
        - openid
        - email
      auth0_subdomain: prod-8ua-1yy9
    Authenticator:
      admin_users:
        - devops@example.com
      auto_login: true
    JupyterHub:
      authenticator_class: auth0

GenericOAuthenticator - OpenID Connect

OpenID Connect is an identity layer on top of the OAuth 2.0 protocol, implemented by various servers and services. While OpenID Connect endpoint discovery is not supported by oauthentiator, you can still configure JupyterHub to authenticate with OpenID Connect providers by specifying all endpoints in the GenericOAuthenticator class.

Auth0

Below is an example on how you can configure the GenericOAuthenticator to authenticate against Auth0.

hub:
  config:
    GenericOAuthenticator:
      client_id: your-client-id
      client_secret: your-client-secret
      oauth_callback_url: https://your-jupyterhub-domain/hub/oauth_callback
      authorize_url: https://your-domain.us.auth0.com/authorize
      token_url: https://your-domain.us.auth0.com/oauth/token
      userdata_url: https://your-domain.us.auth0.com/userinfo
      scope:
        - openid
        - name
        - profile
        - email
      username_key: name
    JupyterHub:
      authenticator_class: generic-oauth
KeyCloak

KeyCloak is an open source based provider of identity management that you can host yourself. Below is an example on how you can configure the GenericOAuthenticator class to authenticate against a KeyCloak server.

To configure an OpenID Connect client, see KeyCloak’s own documentation.

hub:
  config:
    GenericOAuthenticator:
      client_id: your-client-id
      client_secret: your-client-secret
      oauth_callback_url: https://your-jupyterhub-domain/hub/oauth_callback
      authorize_url: https://${host}/auth/realms/${realm}/protocol/openid-connect/auth
      token_url: https://${host}/auth/realms/${realm}/protocol/openid-connect/token
      userdata_url: https://${host}/auth/realms/${realm}/protocol/openid-connect/userinfo
      login_service: keycloak
      username_key: preferred_username
      userdata_params:
        state: state
    JupyterHub:
      authenticator_class: generic-oauth

LDAP and Active Directory

JupyterHub supports LDAP and Active Directory authentication. Read the ldapauthenticator documentation for a full explanation of the available parameters.

Only server_address and bind_dn_template are required, so a minimal configuration would look like this.

hub:
  config:
    JupyterHub:
      authenticator_class: ldapauthenticator.LDAPAuthenticator
    LDAPAuthenticator:
      bind_dn_template:
        - cn={username},ou=edir,ou=people,ou=EXAMPLE-UNIT,o=EXAMPLE
      server_address: ldap.EXAMPLE.org

Another example is provided below, equivalent to the example given in the ldapauthenticator README.

hub:
  config:
    JupyterHub:
      authenticator_class: ldapauthenticator.LDAPAuthenticator
    LDAPAuthenticator:
      allowed_groups:
        - cn=researcher,ou=groups,dc=wikimedia,dc=org
        - cn=operations,ou=groups,dc=wikimedia,dc=org
      bind_dn_template:
        - uid={username},ou=people,dc=wikimedia,dc=org
        - uid={username},ou=developers,dc=wikimedia,dc=org
      escape_userdn: false
      lookup_dn: true
      lookup_dn_search_filter: ({login_attr}={login})
      lookup_dn_search_password: secret
      lookup_dn_search_user: ldap_search_user_technical_account
      lookup_dn_user_dn_attribute: cn
      server_address: ad.EXAMPLE.org
      user_attribute: sAMAccountName
      user_search_base: ou=people,dc=wikimedia,dc=org