Pre-Deployment Checklist
1
Configure Persistent Token Storage
Replace in-memory storage with a persistent store. Use Redis for multi-instance deployments, or SQLite for a single-instance/single-node deployment that needs tokens to survive a restart.
SQLite persists tokens on the local disk of one node — it is not a shared store. For more than one instance behind a load balancer, use Redis so every instance reads the same authorization/refresh/session state.
2
Provide Persistent Signing Keys
Auto-generated keys are lost on restart. Provide stable keys.
3
Enable Refresh Token Flow
For In remote mode, token TTLs are controlled by the upstream identity provider — FrontMCP does not mint its own access/refresh tokens. In local mode, FrontMCP acts as the authorization server and mints its own tokens (signed with
local and remote modes, opt into automatic token refresh.local.signKey).4
Enable HTTPS
All production traffic must use TLS. Configure your reverse proxy or load balancer.
5
Set Expected Audience
Validate the audience (
aud) claim. In transparent mode set expectedAudience. In local and remote mode the tokens FrontMCP issues always name this server’s resource URL as aud and name this server as iss, and are refused anywhere else, even by a server with the same JWT_SECRET; pin FRONTMCP_PUBLIC_URL so that URL doesn’t come from the Host header. Setting expectedAudience there too makes the server accept only tokens issued for the listed resource URLs, whatever URL the request arrived at.Security Requirements
Required
HTTPS only - Never expose auth endpoints over HTTP in production
Persistent token storage - Redis with TLS for multi-instance deployments
Stable signing keys - Provide keys via environment or secrets manager
PKCE enforcement - OAuth 2.1 requires PKCE (S256 only)
Refresh token rotation - Always rotate refresh tokens on use
Audience validation - Validate the
aud claim via expectedAudience in transparent mode; local and remote tokens are bound to this server’s resource URL automatically, or to the expectedAudience you listPinned public URL - Set
FRONTMCP_PUBLIC_URL to a fixed origin. The issuer / resource / OAuth-discovery URLs — and the expected audience of a token — are otherwise derived from request headers. X-Forwarded-Host/X-Forwarded-Proto are ignored by default; only enable them with FRONTMCP_TRUST_PROXY=1 behind a proxy that strips client-supplied forwarded headers. The Web fetch handler (createFetchHandler, Workers, Deno, Bun) takes the address from the request URL the runtime hands it, never from a Host header that disagrees with it.Recommended
Machine ID - Set
MACHINE_ID env var for multi-instance session portabilityRequire registered clients - Keep
auth.requireRegisteredClients at its default (true, local/remote) so every OAuth client must be registered (DCR / pre-registered) or use a CIMD client-id URL. This enforces exact redirect_uri matching and prevents auth-code interception via an unregistered client’s attacker-chosen redirect_uri. In production, remote mode admits only CIMD clients (it has no pre-registered clients and DCR is off); see MCP client registration.Grant only the scopes you mean to - List your scopes in
auth.allowedScopes (local/remote); a client that asks for anything else doesn’t get it.Confidential clients - Clients registered with
client_secret_basic/client_secret_post are authenticated with a constant-time secret check on both the code-exchange and refresh grants.Rate limiting - Protect token endpoints from brute force
Monitoring - Alert on auth failures, unusual patterns
Key rotation - Rotate signing keys periodically (30-90 days)
Scope minimization - Request only necessary scopes
Consent UI - Let users see what they’re authorizing
Configuration Reference
Minimum Production Configuration
Environment Variables
Token Lifetime Guidelines
Key Management
Generating Production Keys
Key Rotation Strategy
Configuration for Key Rotation
Thelocal block accepts a single signKey (and optional jwks containing previous keys for validation during rollover). Rotation is performed by deploying a new server build with an updated signKey while keeping the old key in jwks until in-flight tokens expire.
Redis Configuration
Secure Redis Connection
Redis Data Stored
Monitoring & Alerting
Key Metrics to Monitor
Logging Configuration
Common Production Issues
Tokens invalid after deployment
Tokens invalid after deployment
Cause: Auto-generated keys changed after restart.Solution: Provide persistent signing keys via environment variable:
Session not found errors across instances
Session not found errors across instances
Cause: Using in-memory storage with multiple instances.Solution: Configure shared Redis storage:Also check
MCP_SESSION_SECRET: it must be the same on every instance. A session id minted under a different secret is answered with HTTP 404 (-32000) and the client re-initializes — in every auth mode, including public, where the id is the caller’s only credential. The same happens once, by design, right after you rotate the secret.A 2026-07-28 tool asks its first question again
A 2026-07-28 tool asks its first question again
Cause:
requestState is signed with VAULT_SECRET, else JWT_SECRET, else a random per-process key. With the per-process key, a round answered on another instance (or after a restart) fails verification (mcp-20260728: rejected requestState, reason: 'bad-signature', with a hint naming VAULT_SECRET) and the exchange restarts.Solution: Set VAULT_SECRET (or JWT_SECRET) to the same value on every instance. In production, a server with redis or transport.persistence but neither secret warns about this at startup.JWKS fetch fails intermittently
JWKS fetch fails intermittently
Cause: Network issues or IdP rate limiting.Solution:
- Increase JWKS cache TTL
- Consider inline JWKS for critical IdPs
- Add retry logic with exponential backoff
High latency on token endpoint
High latency on token endpoint
Cause: Redis connection issues or key generation overhead.Solution:
- Use Redis connection pooling
- Pre-generate signing keys (don’t generate on-demand)
- Monitor Redis latency
Security Hardening
Disable Insecure Options
providerConfig:
HTTP Security Headers
Configure your reverse proxy to add security headers:Rate Limiting
FrontMCP includes a built-in session rate limiter with a sliding window algorithm:
The rate limiter tracks requests per key (typically client IP) and provides:
wouldAllow(key)— pre-check without consuming quotagetStats()— monitoring statistics
Deployment Patterns
- Single Instance
- Multi-Instance
- Stateless
Quick Reference
OAuth 2.1 Compliance Checklist
PKCE required for all clients (S256 only)
Refresh token rotation enabled
No implicit grant flow
Authorization codes single-use
Redirect URI exact match
State parameter required
Pre-Production Verification
Next Steps
Authorization Modes
Choose the right mode for your deployment
Tokens & Sessions
Configure token lifetimes and storage
Local OAuth
Built-in OAuth server setup
Remote OAuth
External IdP integration