Skip to Content
Core conceptsAuthentication & sessions

Authentication and sessions

Two credentials, two jobs

Camel Accounts provides identity and issues the OAuth authorization code. The Music API exchanges that code (and PKCE verifier) for a Camel access token, then gives that Camel token to the Ngamia API at /v1/auth/camel. The Ngamia API returns the account-scoped access and refresh tokens used for all subsequent music, billing, library, and activity calls.

The browser does not receive either Ngamia token. The API stores them in cookies named ngamia_music_access and ngamia_music_refresh, both HttpOnly, SameSite=Lax, path /, and Secure when NODE_ENV=production.

CookieDefault lifetimeRole
ngamia_music_accessexpires_in seconds, or 900 seconds when absent/falseyBearer credential for Ngamia API calls
ngamia_music_refresh30 daysObtain a replacement token pair after an upstream 401

OAuth exchange request

POST /api/auth/camel requires an allowed Origin and JSON:

{"code":"authorization-code-from-callback","code_verifier":"the-original-pkce-verifier"}

The verifier must be at least 43 characters. A successful response is { "ok": true } with Set-Cookie headers. Error responses use { "error": { "message": "..." } }. The endpoint does not accept Camel access tokens from the browser; it performs the code exchange itself.

The API calls Camel’s /oauth/token with grant_type=authorization_code, configured client ID and redirect URI, then calls Ngamia /v1/auth/camel. Token pair parsing accepts either the top-level object or a data object containing both string access_token and refresh_token fields.

Authenticated requests and refresh

authenticatedNgamiaFetch reads cookies on the server, sets Accept: application/json, and adds Authorization: Bearer <Ngamia access token>. If neither cookie exists, it returns null; protected routes translate that to a 401 JSON response. If the first upstream response is 401 and a refresh token exists, the helper posts { "refresh_token": "..." } to /v1/auth/refresh, stores the new pair, and retries once. A malformed/unsuccessful refresh clears cookies. No automatic retries occur for 429, 5xx, or network errors (except callers’ own error handling).

Logout

POST /api/auth/logout attempts POST /v1/auth/logout with the current access token and refresh token when both cookies are present. Upstream network errors are swallowed; regardless, local cookies are cleared and the response is { "ok": true }. Therefore ok:true confirms local sign-out, not that remote revocation was confirmed.

Client integration

Use credentialed requests from the configured app origin:

const response = await fetch(`${API_BASE}/api/auth/session`, { credentials: 'include', cache: 'no-store' });

Do not read tokens in JavaScript, attach bearer tokens from the browser, persist them in local storage, or log cookies. The cookies are intentionally inaccessible to browser scripts.

See OAuth flow diagrams and the route reference.

Last updated on