Claxx Auth
Docs
Sign in
User FAQ
  • Reset my password
  • I can't sign in
  • Didn't get reset email
  • Account linking
  • Session expiry
  • Two-factor auth
Admin Guides
Theme Studio
  • Overview
  • Layouts
  • Styling tokens
  • Concept copy
  • Assets & backgrounds
  • Advanced CSS
Admin Shell
  • Users
  • Providers
  • Clients
  • Invitations
Integrations
  • OIDC flow
  • Legacy OAuth flow
  • Provider token brokering
  • Email triggers
  • Webhook events
  • Session contract
Reference
  • API
  • Error codes
  • Event shapes
  • Design tokens
Runbooks
  • Deployment
  • Local operations

Provider Token Brokering

Some downstream apps need more than the user's identity — they need to call the upstream provider's APIs on the user's behalf. Example: media-conductor reading a user's Google Drive, or a workflow tool posting to their Microsoft Teams.

Claxx Auth brokers those upstream tokens so downstream apps never implement upstream OAuth themselves. The user consents once, at Claxx Auth. Claxx Auth holds the refresh token, refreshes upstream tokens on demand, and hands downstream apps a short-lived access token for each request.

This page covers how to ask for a brokered token, how Claxx Auth decides whether to grant it, and the error semantics a client must handle.

Why brokering, not redirection

The architectural mandate is that no downstream Blu app implements standalone OAuth against a third-party IdP. Every third-party identity relationship is owned by Claxx Auth. The benefits:

  • Single consent surface. The user consents to "media-conductor via Claxx Auth" once, not per-app.
  • Centralized refresh. Refresh tokens live in one encrypted store and rotate correctly even for Microsoft's rotating-refresh-token model.
  • Revocation in one place. Admin-level revocation from /admin/users/:id invalidates everything downstream.
  • No secret distribution. Downstream apps never see upstream client secrets or refresh tokens.

The principle

  • Claxx Auth owns the upstream OAuth relationship. The user consents during Claxx Auth sign-in, and Claxx Auth stores the upstream refresh token (KMS-encrypted, at rest in the accounts table).
  • Downstream apps call Claxx Auth, not the upstream provider, when they need a fresh upstream access token.
  • Refresh is transparent. Claxx Auth refreshes upstream tokens on demand; the downstream app receives only the short-lived access token.
  • Tokens are per-client. Each OAuth client must be explicitly allowed to broker tokens for a given provider (via oauth_clients.allowed_provider_tokens).

Consent and scope allowlisting

Two allowlists apply per request:

  1. Client-level: Admins configure each OAuth client's allowedProviderTokens — an array of provider slugs (e.g. ["google", "microsoft"]). A request for google tokens from a client that doesn't list google returns unauthorized_client.
  2. User-level: Each (user, client, provider) tuple has a grant record in provider_token_grants capturing the exact scopes the user consented to. Downstream apps can only request scopes that are a subset of the granted scopes.

When a user signs in via Claxx Auth with additional_scopes=<upstream-scopes> passed through the authorize flow, the upstream provider's consent screen lists those scopes. On success, the grant record is written or updated. Subsequent token requests for that client check the grant.

Endpoint

POST https://auth.example.com/api/provider-tokens/<provider>
Authorization: Bearer <bluauth-access-token>
Content-Type: application/json

{
  "requiredScopes": ["https://www.googleapis.com/auth/drive.readonly"]
}

Where <provider> is the provider slug — one of google, microsoft, github, or a custom OIDC provider slug configured in /admin/providers.

Authentication is the Claxx Auth access token (JWT, ES256) issued to your client via the OIDC flow. The token must belong to the same user whose upstream tokens you want.

Source: server/api/provider-tokens/[provider].post.ts.

Request parameters

FieldRequiredNotes
requiredScopesNoArray of upstream scope strings. When omitted, Claxx Auth returns whatever scopes were last granted for this user/client/provider. When provided, Claxx Auth verifies every entry is present in the stored grant before returning the token.

Scopes use the upstream provider's syntax:

  • Google — full URLs like https://www.googleapis.com/auth/drive.readonly, https://www.googleapis.com/auth/calendar.events.
  • Microsoft — delegated permission names like Mail.Read, Files.Read.All.
  • GitHub — OAuth scopes like repo, read:org.

Claxx Auth does not translate or normalize scope strings; pass them exactly as the upstream documents them.

Response

{
    "success": true,
    "data": {
        "accessToken": "ya29.a0AQ...",
        "expiresIn": 3240,
        "provider": "google",
        "scopes": ["https://www.googleapis.com/auth/drive.readonly", "openid", "email"],
        "clientMetadata": {
            "clientId": "533765293212-abc123.apps.googleusercontent.com",
            "appId": "533765293212"
        }
    }
}
  • accessToken — the upstream provider's access token. Use it as a Bearer token against Google/Microsoft/GitHub APIs directly.
  • expiresIn — seconds until this specific token expires. Never assume the 3600-second default; the value returned here accounts for cache age and refresh recency.
  • scopes — every scope currently associated with the stored token. A superset of requiredScopes.
  • clientMetadata — public identifiers that downstream widgets (notably the Google Drive Picker web component) need alongside the access token:
    • clientMetadata.clientId — the OAuth 2.0 client ID Claxx Auth uses for this provider. Publicly visible on any consent screen; safe to expose to the browser.
    • clientMetadata.appId — present only for google providers. Google Cloud project number derived from the client ID prefix. The Picker widget requires it alongside the OAuth token.
    • Downstream apps must NOT hold their own copies of these identifiers. They correspond to Claxx Auth's Google Cloud project, not the consuming app's. Re-read them on every broker call.

Security headers on the response are forced to Cache-Control: no-store, private — do not log this body, and do not store the access token beyond request scope.

Encryption and storage

  • Upstream access tokens are KMS-encrypted at rest in accounts.access_token and decrypted on demand.
  • Upstream refresh tokens are KMS-encrypted in accounts.refresh_token and never leave Claxx Auth. They are not exposed to any endpoint.
  • Decryption uses the same AWS KMS key as other Claxx Auth secrets (client secrets, webhook secrets).
  • A per-(user, provider) lock (provider-refresh:<userId>:<providerSlug>) serializes refresh attempts so concurrent requests don't waste upstream rate-limit quota or lose a rotated refresh token.

Refresh strategy

When a request arrives:

  1. Claxx Auth looks up the user's accounts row for the provider.
  2. If the stored access token is valid for at least 5 more minutes, it's decrypted and returned directly.
  3. Otherwise, Claxx Auth acquires a refresh lock, re-checks freshness (another thread may have refreshed), and exchanges the stored refresh token at the upstream's token endpoint.
  4. For Microsoft, which rotates refresh tokens on every exchange, Claxx Auth persists the new refresh token atomically alongside the new access token.
  5. The new access token is KMS-encrypted, stored, and returned.

If the upstream rejects the refresh token (user revoked at the provider, admin revoked, scope change required, etc.), Claxx Auth returns upstream_reauth_required. Your app should walk the user through Claxx Auth sign-in again with the scopes they need. See error handling below.

Example: Google Drive on behalf of the user

const bluAuthAccessToken = req.session.bluauthAccessToken;

const res = await fetch('https://auth.example.com/api/provider-tokens/google', {
    method: 'POST',
    headers: {
        Authorization: `Bearer ${bluAuthAccessToken}`,
        'Content-Type': 'application/json'
    },
    body: JSON.stringify({
        requiredScopes: ['https://www.googleapis.com/auth/drive.readonly']
    })
});

if (!res.ok) {
    const err = await res.json();
    if (err.error?.code === 'upstream_reauth_required') {
        return redirectToReauth(err.error.provider, err.error.requiredScopes);
    }
    throw new Error(`provider-token failed: ${err.error?.code}`);
}

const { data } = await res.json();

const drive = await fetch('https://www.googleapis.com/drive/v3/files?pageSize=10', {
    headers: { Authorization: `Bearer ${data.accessToken}` }
});

Error handling

All errors use the Claxx Auth standard error envelope:

{
    "success": false,
    "error": {
        "code": "upstream_reauth_required",
        "message": "Refresh token has been revoked",
        "status": 403
    }
}
Error codeHTTPMeaningRequired action
invalid_token401Claxx Auth access token is missing, malformed, or expired.Re-authenticate the user via OIDC.
unauthorized_client403The calling client is not allowed to broker tokens for this provider.Ask an admin to add the provider slug to the client's allowedProviderTokens.
no_linked_account404The user has never linked this provider.Redirect the user through Claxx Auth sign-in with the provider.
insufficient_scope403The grant does not include every requiredScope. The error payload includes grantedScopes and requiredScopes.Redirect user through Claxx Auth sign-in with the additional scopes.
upstream_reauth_required403The refresh token is revoked / invalid. Claxx Auth has cleared the grant.Redirect user through Claxx Auth sign-in.
upstream_provider_error502Upstream provider returned an error during refresh.Log the providerError detail; retry with exponential backoff. Check provider status page before escalating.
validation_error400requiredScopes was not an array of strings.Fix the request.

Re-authentication flow

When a downstream app receives upstream_reauth_required or insufficient_scope, drive the user back through the OIDC authorize flow with the upstream scopes inlined. Claxx Auth propagates additional_scopes to the upstream provider's consent screen:

GET https://auth.example.com/api/oidc/authorize
  ?client_id=<your-client>
  &redirect_uri=<your-callback>
  &response_type=code
  &scope=openid%20profile%20email
  &state=<opaque>
  &nonce=<opaque>
  &code_challenge=<...>
  &code_challenge_method=S256
  &additional_scopes=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive.readonly

additional_scopes are upstream scopes. Claxx Auth validates they're in the provider's admin-approved list and then forwards them upstream. On successful consent, the grant record is updated and subsequent /api/provider-tokens/... calls succeed.

What Claxx Auth does NOT do

  • Does not expose refresh tokens. Ever. Not via any endpoint, not to any client.
  • Does not proxy API calls. Downstream apps still talk directly to Google/Microsoft/etc. with the brokered access token. Claxx Auth is a token source, not a reverse proxy.
  • Does not support arbitrary providers. Only providers explicitly configured in /admin/providers with refresh-token issuance enabled and allowedProviderTokens populated on the client.
  • Does not support providers that don't return refresh tokens. GitHub's OAuth Apps, for example, issue long-lived access tokens without refresh; those can be brokered but cannot be refreshed — once they expire, the user re-authenticates.
  • Does not validate upstream scopes. Claxx Auth trusts the upstream provider to reject malformed scopes at consent time.

Limitations

  • Not all providers support offline access. Google requires access_type=offline&prompt=consent to issue a refresh token; the Claxx Auth Google provider strategy sets these automatically. Microsoft requires the offline_access scope. For custom OIDC providers, the admin must configure scopes and prompts correctly.
  • Scope additions require consent. A scope that wasn't in the original consent won't retroactively appear in the grant — the user must re-authenticate.
  • Token revocation is not instantaneous. If the user revokes access at the upstream provider directly (e.g. via Google's third-party apps page), Claxx Auth discovers the revocation on the next refresh attempt and returns upstream_reauth_required. In-flight access tokens remain valid upstream until they expire.

On this page

  • Why brokering, not redirection
  • The principle
  • Consent and scope allowlisting
  • Endpoint
  • Request parameters
  • Response
  • Encryption and storage
  • Refresh strategy
  • Example: Google Drive on behalf of the user
  • Error handling
  • Re-authentication flow
  • What Claxx Auth does NOT do
  • Limitations
DocsPrivacyTerms
© 2026 Blu Digital Group