Authentication

This document describes the end-to-end authentication flow for Notebooks Hub across the UI, API, and how it integrates with the identity provider (LabShare Auth).

LabShare Auth Application Configuration

To integrate Notebooks Hub with LabShare Auth, configure the following settings in your LabShare Auth application:

Application Settings:

  • Application Type: Web App

  • Login/Logout: Show logout prompt

  • Token Configuration: Include User Info in ID Token

  • Advanced Features: Disable Profile Photo Access

  • Grant Types: authorization_code, refresh_token

  • Response Types: code

  • Token Endpoint Auth Method: client_secret_post

Environment Configuration

Configure the following environment variables with values from your LabShare Auth application:

# LabShare Auth OIDC Configuration
SERVICES_AUTH_URL='https://your-labshare-auth-domain.com'
SERVICES_AUTH_TENANT='your-tenant-identifier'
SERVICES_AUTH_CLIENT_ID='your-client-id'
SERVICES_AUTH_CLIENT_SECRET='your-client-secret'
SERVICES_AUTH_REDIRECT_URL='https://your-app-domain.com/auth/callback'

Note: Replace the placeholder values with your actual LabShare Auth configuration. The SERVICES_AUTH_REDIRECT_URL should match the callback URL configured in your LabShare Auth application.

High-level sequence

  1. UI calls API /auth/authorize to obtain an IdP authorization URL and redirects the user to the IdP (PKCE is used; the verifier is stored in the API session).

  2. After user login/consent, IdP redirects back to the UI with code in the URL.

  3. UI calls API /auth/token with the code. API validates the PKCE code_verifier from session and exchanges the code with the IdP for tokens.

  4. UI stores access_token, id_token, refresh_token, and expires_at locally and begins calling API endpoints with Authorization: Bearer <access_token>.

  5. API authenticates requests by validating the JWT and, if needed, initializes the request session profile by calling the IdP /me endpoint.

  6. For protected resources, API checks authorization (OpenFGA) before serving responses.

  7. UI refreshes tokens via /auth/refresh when near expiry; on logout, UI calls /auth/logout to get a provider logout URL and redirects the browser.

API endpoints (authentication)

  • POST /auth/authorize - Returns an authorization URL for the IdP and stores PKCE code_verifier in the API session.

  • POST /auth/token - Exchanges the authorization code for tokens using the stored PKCE verifier.

  • POST /auth/refresh - Refreshes expired access tokens using the refresh token.

  • POST /auth/logout - Returns a logout URL pointing to the IdP end-session endpoint.

The API uses the openid-client library for OIDC operations including PKCE code generation, token exchange, and refresh flows.

API request authentication

  • The API configures an OAuth/JWT strategy that validates bearer tokens and ensures a valid email exists in the session profile. On each request, if the session is not initialized, the API calls the IdP /me endpoint with the bearer token to populate the session (email, provider, token).

Token and session details

  • Tokens: access_token is sent as a bearer token on API calls; id_token is used for user profile; refresh_token is used by the UI to refresh.

  • Session: The API stores PKCE code_verifier and a minimal profile (email, provider, token) in the server-side session per user.

  • Scopes: Default scopes requested include openid profile offline_access email tenant identity_provider on the API OIDC client; JupyterHub requests openid profile email.

Security considerations

  • Use HTTPS in all environments to protect tokens in transit.

  • Keep client_secret and refresh_token secure; never expose secrets in client code or logs.

  • Limit token lifetimes and rely on refresh when necessary; the UI refreshes proactively before expiry.

  • Validate issuer and JWKS configuration in the API, and ensure aud, iss, and signature checks are correct in the JWT validation middleware.

  • Configure CORS and withCredentials appropriately so the API session is bound to the browser and cannot be replayed cross-site.

Troubleshooting Tips

Missing code_verifier Error:

  • If /auth/token fails with Missing code_verifier, ensure the same browser session initiated /auth/authorize and that cookies are not blocked.

  • Verify that Set-Cookie headers are being set in API responses, as the code_verifier is persisted through session cookies for the PKCE flow.

  • If cookies are disabled or cannot be set in the backend service, the code_verifier cannot be persisted through the session and login will fail.

Nonce Mismatch Error:

  • If /auth/token fails with Token exchange failed: RPError: nonce mismatch, expected undefined, got: [nonce_value], ensure that Legacy application compatibility is disabled in the Advanced features section of your LabShare Auth application configuration.