CrabGlamp

OAuth and token storage

How CrabGlamp stores third-party OAuth refresh tokens, the encryption at rest, the refresh flow that converts them into short-lived access tokens, and how it handles a dead or failing token. This page is the security and trust reference for the App integrations surface — read it when answering a buyer's questions about credential storage.

Last updated:

CrabGlamp brokers OAuth for the supported third-party services directly — no external token service, no Nango, no Supabase Auth in the loop.

What is stored

For each connection, CrabGlamp stores:

  • Which account it belongs to.
  • The provider (Google, GitHub, Spotify).
  • The OAuth scope list.
  • Your email at the provider (for display in the dashboard).
  • The refresh token, encrypted at rest (AES-256-GCM).
  • A cached access token plus its expiry (refreshed on demand).
  • A status: active or error. There is no separate "expired" state — an expired refresh token flips a connection from active to error on the next refresh attempt.

Encryption at rest

The refresh token is the load-bearing secret. It is encrypted with AES-256-GCM using a key held in CrabGlamp's environment configuration, separate from the database. Only the ciphertext is stored; nothing readable ends up in a database snapshot, a log file, or a backup.

The cached access token is also stored encrypted at rest (AES-256-GCM). It is short-lived (about 1 hour for Google and Spotify; GitHub tokens are long-lived) and re-derivable from the refresh token, so even if one leaked it would expire fast.

The refresh flow

When an Agent calls GET /api/apps/{connection-id}/token:

  1. If the cached access token is still valid (more than 5 minutes remaining), it is returned as-is.
  2. Otherwise CrabGlamp uses the refresh token to get a new access token from the provider, with a 10-second timeout on that call.
  3. If the provider rotates the refresh token, the new one is re-encrypted and stored; the new access token is cached.
  4. The access token is returned to the Agent.

Concurrent token fetches are safe: CrabGlamp serializes refreshes per connection, so two Agents calling at the same time can't race and invalidate each other's token.

Error classification

Your Agent sees one of two error responses:

  • 410 Gone (connection_error) — the refresh token is dead: revoked at the provider, or expired. The connection is marked error; re-authorize from the dashboard.
  • 503 (refresh_unavailable) — a transient failure (provider 5xx, network timeout) or a platform-side OAuth misconfiguration. The connection stays active; retry with backoff. If a provider's connections all 503, it is likely a misconfiguration on our side — contact security@crabglamp.com.

Unknown provider errors default to the 503 (retry) path rather than marking the connection dead: a falsely-active connection costs one extra retry, while a falsely-errored one costs you a broken integration that needs manual re-authorization.

Revocation

Revoking from the dashboard sends a best-effort revoke to the provider, then removes the connection. Removing it on CrabGlamp's side is the guarantee — even if the provider revoke fails (network blip), the connection is gone and no Agent can fetch a token.

If you revoke from the provider side without going through the dashboard, the next Agent fetch fails and the connection is marked error the next time it's used. No background job is needed.

Related

View as Markdown — the same content as plain text for AI assistants and offline reading.

Was this helpful?