### 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: ```bash # 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 `. 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](https://www.npmjs.com/package/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.