FMG and MRC are separate integrations. This guide covers FMG (
fmg.* scopes). For MyRepChat texting, see the MRC APIs → OAuth guide — same flow, its own Client ID/Secret and mrc.* scopes.What FMG provides
FMG provisions your application per environment — sandbox first, then production. Build and test against sandbox, then repeat with the production values.What you provide
You give FMG one thing up front:
FMG registers these in its OAuth service (Stytch) against your Client ID. Only registered URIs are accepted at authorization time.
Why the redirect URI matters
The redirect URI is the most security-critical value you register, because it is where the authorizationcode is delivered:
- After the subscriber approves consent, the authorization server sends the browser to
redirect_uri?code=.... Whoever controls that URL receives the code and can exchange it for tokens. - So the authorization server treats your registered URIs as a strict allowlist: the
redirect_uriin the authorize request must match a registered URI exactly — scheme, host, port, and path. A mismatch is rejected before any code is issued. - This closes authorization-code interception / open-redirect attacks — an attacker can’t substitute their own callback to capture the code, because an unregistered URI never matches.
- It must be HTTPS and a URL your server controls (no wildcards, no fragments). Register every environment’s callback, since sandbox and production use different values.
Flow at a glance
1
Generate PKCE + state
Server-side, create a
code_verifier, its code_challenge (S256), and a random state.2
Redirect to authorize
Send the user’s browser to the Authorize URL with your request parameters.
3
Handle the callback
FMG redirects back with
code and state. Validate state.4
Exchange code for tokens
Server-side
POST to the Token URL with the code, code_verifier, and client_secret.5
Call FMG APIs
Use the
access_token as a Bearer token. Refresh it when it expires.Step 1 — Generate PKCE parameters
Generate these on your server and storecode_verifier + state in the user’s server-side session:
Step 2 — Redirect to authorization
Redirect the user’s browser to the Authorize URL:
The user authenticates with FMG and approves a consent screen listing your requested permissions.
Step 3 — Handle the callback
FMG redirects to yourredirect_uri:
- Compare
stateagainst the session value — abort on mismatch (CSRF). - Retrieve the
code_verifierfrom the session. - Clear both from the session — they are single-use.
Step 4 — Exchange the code for tokens
Server-sidePOST to the Token URL. Authenticate with your client_secret:
refresh_token is only returned when the offline_access scope is granted. Store both tokens securely (server-side session or HttpOnly cookie — never localStorage).
Step 5 — Call FMG Connect APIs
Send the access token as a Bearer token:Step 6 — Refresh the access token
When the access token expires (401 response), use the refresh token to get a new one without sending the user through the flow again:
Scopes
Request exactly the scopes FMG assigned you — requesting an unprovisioned scope fails.Endpoints
Errors
Security requirements
- PKCE (S256) for every request; keep the
code_verifierserver-side. - Unique
stateper request; validate on callback. - Token exchange and refresh are server-side only — never expose
client_secretorcode_verifierto the browser. - HTTPS for all redirect URIs and API calls.
- Store tokens in HttpOnly cookies or server-side sessions.