Skip to main content
The supported profile is a server-backed confidential client, using authorization code with S256 PKCE, deliberate consent, and client_secret_basic. Browser-only and mobile-only public clients are unsupported. Keep client secrets, access tokens and refresh tokens on the server; give the browser an opaque, HttpOnly session cookie. Register your application first.

Complete the flow

  1. Discover the issuer at https://api.sharedgraph.com/api/auth/.well-known/openid-configuration. Its issuer is https://api.sharedgraph.com/api/auth. Use the discovered endpoints and signing keys; discovery and JWKS need no credential.
  2. Create a short-lived, single-use server-side login transaction bound to this browser and application. Generate unpredictable state, nonce and a PKCE verifier. Store them securely; send only the S256 challenge in the authorization request.
  3. Redirect the browser to the discovered authorization endpoint with response_type=code, your client_id, the exact registered redirect_uri, space-separated requested scope, state, nonce, code_challenge and code_challenge_method=S256. Request prompt=consent. The provider handles account login and deliberate consent with its own account cookie.
  4. On your callback, consume the login transaction once. Validate state and the authorization response. Exchange the code server-to-server at /api/auth/oauth2/token, using HTTP Basic client authentication, Content-Type: application/x-www-form-urlencoded, grant_type=authorization_code, the code, the same redirect URI and code_verifier. Use a maintained OIDC library to validate the ID token, including issuer, audience, signature and nonce.
  5. Reject any granted scope outside the requested set. The OIDC pairwise subject is not the canonical actor identifier. Call GET /api/session with Authorization: Bearer <access_token> and bind its actorId, appId, immutable grantId and scopes to your application session. Check that appId is your registered client identifier.
  6. Seal token state server-side and establish an application-bound browser session. Revalidate canonical authority before protected operations and again before publishing their results. The starter implements this path.
OAuth authorization and consent are browser navigation/provider surfaces. Do not forward the user’s provider account cookie into your application’s bearer API transport, or expose tokens to browser JavaScript. Registration does not itself authorize an application for a user.

Token lifetime and rotation

Access tokens live 300 seconds. Refresh tokens live 30 days, subject to earlier revocation or other loss of authority. offline_access requests refresh capability. These lifetimes do not promise continued authority: canonical session admission still applies. Refresh at the token endpoint with HTTP Basic authentication and form fields grant_type=refresh_token and refresh_token. Refresh scope cannot expand the grant. Rotation is strict, with no reuse interval: atomically replace the old refresh token with the returned token and never spend the parent again. Serialize refresh across every server instance using current durable storage, rather than a process-local lock. If completion is uncertain, retire the session and ask for authorization again. Refreshed authority must preserve actor, application, grant and exact scope set. The starter’s application session has a separate fixed one-hour admission lifetime and a 15-second durable refresh lease. These are starter choices, not OAuth token lifetimes. Logout retires its durable session and expires its cookie; local logout is distinct from revoking the network grant. Token introspection and revocation also use confidential client Basic authentication.

Origins and headers

The URL itself must use the configured network origin. Do not forward browser Cookie, Origin or Host into backend transport. See lifecycle and safety for response admission signals and mutation retries.