
Security patterns
OAuth access and refresh tokens are bearer credentials: anyone who has them can act as your user. Storing them safely is one of the most important parts of building secure integrations.
This guide covers concrete patterns for web backends, SPAs, and mobile apps—without diving into any vendor-specific infrastructure.
Most providers give you some combination of:
All three are secrets and should be handled like passwords. OWASP’s secrets management guidance explicitly treats API tokens as sensitive data that must be stored and transmitted securely.
Whenever possible, keep tokens on the server, not in the browser.
Common pattern:
Cloud providers recommend using dedicated secret stores for highly sensitive values and keeping encryption keys separate from the data.
CREATE TABLE oauth_tokens ( id SERIAL PRIMARY KEY, user_id UUID NOT NULL, provider TEXT NOT NULL, access_token BYTEA NOT NULL, -- encrypted refresh_token BYTEA, expires_at TIMESTAMPTZ, UNIQUE (user_id, provider) );
OWASP explicitly warns against exposing secrets in logs and monitoring systems.
For SPAs and other “public clients”, there is no truly secure storage in the browser. Any data readable by JavaScript can be stolen via XSS. OWASP and others warn against keeping long-lived tokens in localStorage for this reason.
A commonly recommended pattern for SPAs is:
Example cookie flags from the server side:
Set-Cookie: rt_session=abc123; HttpOnly; Secure; SameSite=Strict; Path=/api/
Because the cookie is HttpOnly, JavaScript can’t read it, which reduces exposure from XSS.
On native platforms, store tokens in OS-level secure stores:
These systems are designed specifically for long-lived secrets and are recommended over flat files or standard app storage.
Short-lived access tokens limit blast radius if leaked; refresh tokens support long-lived sessions without constant logins. This model is recommended in OAuth 2.0 guidance and by major IdPs like Auth0 and Google.
OWASP’s secrets cheat sheet and multiple cloud security guides stress: never hard-code tokens in source code or commit them to Git; use secret managers or encrypted config instead.
Before shipping, check that:
If you follow these patterns, you dramatically reduce the chance that a leaked token turns into a serious breach—without making your OAuth integration painful to use.