Skip to content
Integrations

OAuth — per-user auth

How to wire up OAuth flows on FlareX — redirect URIs, state, code exchange, and storing tokens.

Updated

OAuth is the standard way for an app to act on behalf of a specific user of a 3rd party — read their Google Calendar, post to their Twitter, list their GitHub repos. Different from a single API key, which lets you act as a single account regardless of who's signed in.

This doc covers the 3-legged OAuth pattern (the user clicks "sign in with X" → consent screen → back to your app). Almost every consumer-grade provider works this way.

The flow

┌───────────┐                        ┌───────────────┐                 ┌───────────────┐
│   user    │ 1. click "connect X"   │   your app    │ 2. redirect to  │   provider    │
│  browser  │ ──────────────────────▶│ on flarex     │ ──────────────▶ │ (e.g. Google) │
└───────────┘                        └───────────────┘                 └───────────────┘
                                                                              │
                                              ┌───────────────────────────────┘
                                              │ 3. user logs in + consents
                                              ▼
                                        ┌───────────────┐
                                        │   provider    │
                                        └───────────────┘
                                              │
                                              │ 4. redirect back with ?code=…
                                              ▼
┌───────────┐                        ┌───────────────┐
│   user    │ 6. session cookie set  │   your app    │ 5. POST code → access token
│  browser  │ ◀──────────────────────│ on flarex     │ ◀──── HTTP ──── provider
└───────────┘                        └───────────────┘

Three URLs you'll wire up:

  1. GET /auth/<provider>/login — generate a state, store it briefly, redirect to provider.
  2. GET /auth/<provider>/callback?code=…&state=… — verify state, exchange code for token, store token, set session.
  3. POST /auth/<provider>/logout — clear the session, optionally revoke the token at the provider.

Step 1: Register your app with the provider

Most providers want a redirect URI when you create the OAuth app. For your FlareX app, that's:

https://<your-app>-<hex>.flarex.app/auth/<provider>/callback

(Or the equivalent on your custom domain if you've set one up.)

Register both the FlareX-branded URL and your custom domain — providers don't accept wildcards. If you switch domains later, register the new one before flipping over.

Heads up

Localhost redirect URIs (http://localhost:3000/...) won't work with FlareX-hosted apps. Use a separate test app + test redirect URI when developing locally if you need that workflow.

Step 2: Add the credentials to Secrets

Most providers give you two values:

  • Client ID — public, embedded in the auth URL
  • Client secret — private, never shipped to the browser

Add both to Secrets:

GOOGLE_CLIENT_ID=...
GOOGLE_CLIENT_SECRET=...
GOOGLE_REDIRECT_URI=https://my-app-abc123.flarex.app/auth/google/callback

Step 3: Describe the flow to FlareX

Add Google OAuth. Use GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET,
GOOGLE_REDIRECT_URI from Secrets. Scopes: openid, email, profile,
https://www.googleapis.com/auth/calendar.readonly.

After successful auth, store the access_token + refresh_token in the
oauth_tokens table keyed by user_id. Set a session cookie that lasts
30 days.

FlareX writes the three routes, handles state (CSRF protection), exchanges the code for tokens, stores them, and sets the session.

What FlareX picks for you

  • State: a cryptographically random value stored in a short-lived (5 min) Redis key, verified on callback. Prevents CSRF.
  • PKCE: where the provider supports it (Google, Twitter, Microsoft), FlareX uses it by default. Adds replay protection without extra config.
  • Token storage: encrypted at rest in the workspace database. Refresh tokens are kept for the lifetime of the user account; revocation deletes them.
  • Session cookie: signed with SESSION_SECRET, HttpOnly, Secure, SameSite=Lax.

Refresh tokens

When the access token expires (typically 1h), don't fail the request — refresh transparently. Ask FlareX:

On any provider call that returns 401, attempt to refresh the access
token using the stored refresh_token. If the refresh fails, mark the
connection as "needs reauth" and surface a banner asking the user to
reconnect.

Multiple providers

Wire up "Sign in with GitHub" + "Sign in with Google" + "Sign in with Discord" in one app. Each gets its own pair of routes. Tell FlareX:

Add OAuth for GitHub, Google, and Discord. Each is its own button on
the /signin page. Successful login from any provider lands the user
in the same session — match by email.

The "match by email" piece is your call: some apps want one account per provider, others want one account per email. Be explicit.

OAuth for an integration vs. for sign-in

Two flavours of the same flow:

UseWhat you keepWhat you do with it
Sign-in (auth)Profile (email, id, name)Set a session for your app; identify the user
Integration (authz)Access + refresh tokensCall the provider's API on the user's behalf

Tell FlareX which one you want. Sign-in is simpler (no token storage). Integration is what you need for "post to my Twitter" type features.

What's next

OAuth — per-user auth · FlareX