Skip to main content
The Photon dashboard is an OAuth 2.1 and OpenID Connect provider. Register an OAuth app, send users through the authorization code flow, and call the Dashboard API with the resulting bearer token — limited to exactly the scopes the user consented to.
OAuth tokens authenticate users against the Dashboard API on app.photon.codes. The Spectrum API on spectrum.photon.codes uses per-project HTTP Basic credentials instead; the two credential systems are separate and not interchangeable.

Endpoints

Discovery

Because the issuer contains a path component (/api/auth), the metadata documents live at the RFC 8414 §3.1 path-insertion URLs — the issuer’s path goes after the well-known segment:
Libraries that derive the metadata URL from the issuer per RFC 8414 resolve these automatically. Some OIDC clients instead append /.well-known/openid-configuration to the issuer or probe the domain root — both of those 404 here, so configure the discovery URL (or the individual endpoints) explicitly in that case.

Create an OAuth app

In the dashboard, open Developer → Apps and create an app. You’ll choose:
  • Name, logo, homepage — shown to users on the consent screen.
  • Redirect URIs — an exact-match allowlist. The redirect_uri in your authorization request must match one of these character for character.
  • Client typeconfidential for server-side apps that can keep a secret, or public for native and browser-based apps that can’t. Public clients get no secret and rely on PKCE alone.
  • Scopes — the maximum set your app may request. Authorization requests for scopes outside this set are rejected with invalid_scope.
The client_secret is shown once, when the app is created. It’s stored hashed and can’t be retrieved later — keep it in a secrets manager. If you lose it, rotate it from the app’s page in the dashboard.

Authorization code flow

PKCE with the S256 challenge method is required for every client, confidential ones included. plain is not accepted.
1

Generate a PKCE verifier and challenge

2

Send the user to the authorization endpoint

scope is a space-separated list (URL-encoded). The user signs in to Photon, reviews the requested scopes on the consent screen, and on approval is redirected to your redirect_uri with code and your state in the query string. Verify state matches what you sent before using the code.
3

Exchange the code for tokens

Confidential clients authenticate with client_secret in the body as shown, or with HTTP Basic (client_id:client_secret) — both are accepted. Public clients omit the secret.
The access token is opaque — don’t try to parse it. id_token is only present when openid was granted, and refresh_token only when offline_access was granted.
4

Call the Dashboard API

A missing, expired, or revoked token returns 401. A valid token missing the scope an endpoint requires returns 403 with insufficient_scope: <scope> in the message.

Refresh tokens

Request the offline_access scope to receive a refresh token, then exchange it when the access token expires:
Refresh tokens rotate: each exchange returns a new refresh token and invalidates the old one, so always store the one from the latest response. Refresh tokens live for 30 days; an app that refreshes at least that often stays connected indefinitely.

Scopes

Access-token lifetimes

Access tokens live 1 hour by default. Sensitive scopes shorten that: billing:write tokens live 5 minutes, and every other :write scope caps the token at 15 minutes. When one token carries several scopes, the shortest lifetime wins — a token with projects:read and projects:write expires after 15 minutes. Apps that hold write scopes should request offline_access and refresh rather than treating the access token as long-lived.

OpenID Connect

With the openid scope granted, the token response includes an id_token and the UserInfo endpoint returns the user’s claims:
The id_token is a JWT signed with EdDSA (Ed25519) — verify it against the JWKS endpoint, and make sure your JWT library supports EdDSA before relying on local verification. Available claims include sub, email, email_verified, name, and picture, gated by the profile and email scopes.

Revoking access

Apps can revoke a token they hold:
Users can also withdraw an app’s access at any time from their dashboard settings, which revokes the consent along with every live token issued under it. Revocation propagates to API servers within about a minute.

Limitations

  • No machine-to-machine tokens. The client_credentials grant is not supported — every access token represents a user who went through the consent flow. For server-to-server project automation, use the Spectrum API’s project credentials instead.
  • No dynamic client registration. The discovery document advertises a registration_endpoint, but programmatic registration is disabled — create apps in the dashboard.
  • S256 only. The plain PKCE challenge method is rejected, and PKCE cannot be skipped.