Skip to main content
FrontMCP includes a built-in OAuth 2.1 authorization server for self-contained authentication scenarios.
The built-in login page accepts any email format without validation. Replace with a real identity provider for production use.

Basic Configuration

@FrontMcp({
  info: { name: 'MyServer', version: '1.0.0' },
  auth: {
    mode: 'orchestrated',
    type: 'local',
    consent: { enabled: true },
  },
})
export class Server {}

Configuration Options

OptionTypeDefaultDescription
consentConsentConfig{ enabled: false }Consent UI configuration
sessionMode'stateful' | 'stateless''stateful'Session management strategy
tokenStorageobject{ type: 'memory' }Token storage backend
allowDefaultPublicbooleanfalseAllow unauthenticated access
anonymousScopesstring[]['anonymous']Scopes for anonymous sessions
incrementalAuthIncrementalAuthConfig{ enabled: true }Progressive authorization config

OAuth Endpoints

Local mode exposes standard OAuth 2.1 endpoints:
EndpointMethodDescription
/oauth/authorizeGETStart authorization flow
/oauth/tokenPOSTExchange code for tokens
/oauth/registerPOSTDynamic Client Registration
/oauth/userinfoGETGet user profile
/.well-known/oauth-authorization-serverGETServer metadata
/.well-known/jwks.jsonGETPublic signing keys

Authorization Request

GET /oauth/authorize
  ?response_type=code
  &client_id=your-client-id
  &redirect_uri=http://localhost:3000/callback
  &scope=openid profile
  &state=random-state
  &code_challenge=base64url(sha256(verifier))
  &code_challenge_method=S256

Token Exchange

POST /oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&code=authorization-code
&redirect_uri=http://localhost:3000/callback
&client_id=your-client-id
&code_verifier=original-verifier

Key Management

Auto-Generated Keys

By default, FrontMCP generates RS256 keys at startup:
auth: {
  mode: 'orchestrated',
  type: 'local',
  // Keys auto-generated
}
Auto-generated keys are lost on restart. Existing tokens become invalid.

Persistent Keys

Provide keys for stable token validation:
auth: {
  mode: 'orchestrated',
  type: 'local',
  local: {
    signKey: {
      kty: 'RSA',
      kid: 'my-key-id',
      alg: 'RS256',
      n: '...',  // RSA modulus
      e: 'AQAB',
      d: '...',  // Private exponent
      // ... other JWK parameters
    },
  },
}

ES256 Keys

Use ES256 for smaller tokens:
auth: {
  mode: 'orchestrated',
  type: 'local',
  local: {
    signKey: {
      kty: 'EC',
      crv: 'P-256',
      x: '...',
      y: '...',
      d: '...',
    },
  },
}

Dynamic Client Registration

DCR allows clients to register programmatically. DCR is enabled by default in development.

Registration Request

POST /oauth/register
Content-Type: application/json

{
  "redirect_uris": ["http://localhost:3000/callback"],
  "client_name": "My Application",
  "token_endpoint_auth_method": "none",
  "grant_types": ["authorization_code", "refresh_token"],
  "response_types": ["code"]
}

Registration Response

{
  "client_id": "generated-uuid",
  "client_id_issued_at": 1234567890,
  "redirect_uris": ["http://localhost:3000/callback"],
  "client_name": "My Application",
  "token_endpoint_auth_method": "none",
  "grant_types": ["authorization_code", "refresh_token"],
  "response_types": ["code"]
}
DCR is intended for development only. In production, pre-register clients. DCR only allows localhost redirect URIs by default.

Per-App Configuration

Configure local auth per app with splitByApp: true:
@App({
  name: 'Billing',
  auth: {
    mode: 'orchestrated',
    type: 'local',
    consent: { enabled: true },
  },
})
export class BillingApp {}

@App({
  name: 'Analytics',
  auth: {
    mode: 'orchestrated',
    type: 'local',
  },
})
export class AnalyticsApp {}

@FrontMcp({
  info: { name: 'Suite', version: '1.0.0' },
  apps: [BillingApp, AnalyticsApp],
  splitByApp: true,
})
export class Server {}

Token Storage

In-Memory (Development)

auth: {
  mode: 'orchestrated',
  type: 'local',
  tokenStorage: { type: 'memory' },
}

Redis (Production)

auth: {
  mode: 'orchestrated',
  type: 'local',
  tokenStorage: {
    type: 'redis',
    config: {
      host: process.env.REDIS_HOST!,
      port: parseInt(process.env.REDIS_PORT || '6379'),
      password: process.env.REDIS_PASSWORD,
      keyPrefix: 'myapp:auth:',
    },
  },
}

Enable and customize the consent UI:
auth: {
  mode: 'orchestrated',
  type: 'local',
  consent: {
    enabled: true,
    groupByApp: true,           // Group tools by app
    showDescriptions: true,     // Show tool descriptions
    allowSelectAll: true,       // Allow selecting all tools
    requireSelection: true,     // Require at least one tool
    rememberConsent: true,      // Remember for future sessions
    excludedTools: ['health'],  // Always available tools
    defaultSelectedTools: [],   // Pre-selected tools
    customMessage: 'Select the tools you want to grant access to.',
  },
}

Complete Example

import { FrontMcp } from '@frontmcp/sdk';

@FrontMcp({
  info: { name: 'MyServer', version: '1.0.0' },
  auth: {
    mode: 'orchestrated',
    type: 'local',
    consent: { enabled: true },
    sessionMode: 'stateful',
    tokenStorage: {
      type: 'redis',
      config: {
        host: process.env.REDIS_HOST!,
        port: parseInt(process.env.REDIS_PORT || '6379'),
        password: process.env.REDIS_PASSWORD,
      },
    },
    refresh: {
      enabled: true,
      skewSeconds: 60,
    },
    local: {
      signKey: JSON.parse(process.env.JWT_SIGNING_KEY!),
    },
    incrementalAuth: {
      enabled: true,
      allowSkip: true,
      skippedAppBehavior: 'require-auth',
    },
  },
})
export class Server {}

Troubleshooting

Auto-generated keys are lost on restart. Either:
  • Provide persistent keys via local.signKey
  • Use Redis for token storage
  • Accept that users must re-authenticate
Ensure you’re using S256 challenge method and the code_verifier matches the original code_challenge.
When running multiple server instances, use Redis for token storage to share session state.

Next Steps

Remote OAuth

Connect to external identity providers

Progressive Authorization

Implement incremental app authorization

Production Checklist

Security requirements for deployment

Tokens & Sessions

Configure token lifetimes