Configure Custom OAuth
This works with any OAuth 2.0 / OpenID Connect provider. Authentik is used as the example here, but the same approach applies to Keycloak, Authelia, Kanidm, Casdoor, or any OIDC-compliant provider.
-
Install the authenticator
Terminal window sudo /opt/tljh/hub/bin/pip install oauthenticator -
Create an OAuth application in Authentik
In the Authentik admin interface:
- Go to Applications > Providers > Create
- Provider type: OAuth2/OpenID Connect
- Name:
JupyterHub - Authorization flow: select your default authorization flow
- Client type: Confidential
- Redirect URIs:
http://<your-ip>/hub/oauth_callback - Scopes:
openid,email,profile
After creation, note down:
- Client ID
- Client Secret
- OpenID Connect Discovery URL:
https://<authentik-domain>/application/o/<app-slug>/.well-known/openid-configuration
Then go to Applications > Applications > Create:
- Name:
JupyterHub - Slug:
jupyterhub - Provider: select the provider you just created
-
Find your provider’s endpoints
You can get all endpoints from the discovery URL:
Terminal window curl -s https://<authentik-domain>/application/o/jupyterhub/.well-known/openid-configuration | python3 -m json.toolNote the values for:
authorization_endpointtoken_endpointuserinfo_endpoint
For Authentik these will typically be:
- Authorize:
https://<authentik-domain>/application/o/authorize/ - Token:
https://<authentik-domain>/application/o/token/ - Userinfo:
https://<authentik-domain>/application/o/userinfo/
-
Configure TLJH
Terminal window sudo tljh-config set auth.type oauthenticator.generic.GenericOAuthenticatorsudo tljh-config set auth.GenericOAuthenticator.client_id '<client-id>'sudo tljh-config set auth.GenericOAuthenticator.client_secret '<client-secret>'sudo tljh-config set auth.GenericOAuthenticator.oauth_callback_url 'http://<your-ip>/hub/oauth_callback'sudo tljh-config set auth.GenericOAuthenticator.authorize_url 'https://<authentik-domain>/application/o/authorize/'sudo tljh-config set auth.GenericOAuthenticator.token_url 'https://<authentik-domain>/application/o/token/'sudo tljh-config set auth.GenericOAuthenticator.userdata_url 'https://<authentik-domain>/application/o/userinfo/'sudo tljh-config set auth.GenericOAuthenticator.scope '["openid", "email", "profile"]'sudo tljh-config set auth.GenericOAuthenticator.login_service 'Authentik'# The claim in the userinfo response that contains the usernamesudo tljh-config set auth.GenericOAuthenticator.username_claim 'preferred_username'# Set yourself as adminsudo tljh-config set auth.GenericOAuthenticator.admin_users '["leo"]'# Allow specific userssudo tljh-config set auth.GenericOAuthenticator.allowed_users '["leo", "student1", "student2"]'sudo tljh-config reload hub -
Allow all users from the provider (optional)
If you want anyone who can authenticate with Authentik to access JupyterHub without maintaining an allowed users list:
Terminal window sudo tljh-config set auth.GenericOAuthenticator.allow_all trueUse this when Authentik itself handles access control (e.g. only users assigned to the JupyterHub application in Authentik can authenticate). This is the recommended approach if you manage group membership in Authentik rather than in JupyterHub.
-
Map groups from Authentik (optional)
If Authentik includes group membership in the userinfo response (it does by default under the
groupsclaim):Terminal window sudo tljh-config set auth.GenericOAuthenticator.manage_groups truesudo tljh-config set auth.GenericOAuthenticator.claim_groups_key 'groups'sudo tljh-config set auth.GenericOAuthenticator.allowed_groups '["cs-students"]'sudo tljh-config set auth.GenericOAuthenticator.admin_groups '["cs-teachers"]'This maps Authentik groups directly to JupyterHub roles. Users in
cs-teachersget admin access, users incs-studentsget regular access, and anyone not in either group is denied.
Adapting for other providers
The only things that change between providers are the three endpoint URLs and the username_claim. Common values:
| Provider | Authorize | Token | Userinfo | Username claim |
|---|---|---|---|---|
| Authentik | /application/o/authorize/ | /application/o/token/ | /application/o/userinfo/ | preferred_username |
| Keycloak | /realms/<realm>/protocol/openid-connect/auth | /realms/<realm>/protocol/openid-connect/token | /realms/<realm>/protocol/openid-connect/userinfo | preferred_username |
| Authelia | /api/oidc/authorization | /api/oidc/token | /api/oidc/userinfo | preferred_username |
| Kanidm | /ui/oauth2 | /oauth2/token | /oauth2/openid/<client>/userinfo | preferred_username |
| Casdoor | /login/oauth/authorize | /api/login/oauth/access_token | /api/userinfo | preferred_username |
Any provider that publishes a .well-known/openid-configuration endpoint will list its URLs there.