Skip to main content
FrontMCP supports two approaches for integrating external identity providers:

Transparent Mode

Pass-through tokens from the IdP. FrontMCP validates but doesn’t issue tokens.Best for: Single IdP, existing auth infrastructure

Orchestrated Remote

FrontMCP acts as OAuth server, proxying user authentication to upstream IdP.Best for: Multi-provider, progressive auth, federated scenarios

Transparent Mode

Direct token pass-through from external identity provider.
@FrontMcp({
  info: { name: 'MyServer', version: '1.0.0' },
  auth: {
    mode: 'transparent',
    provider: 'https://auth.example.com',
    expectedAudience: 'https://api.myservice.com',
  },
})
export class Server {}

Configuration Options

OptionTypeDefaultDescription
providerstringRequiredBase URL of the identity provider
providerConfig.jwksUristringAuto-discoveredCustom JWKS endpoint
providerConfig.jwksJSONWebKeySet-Inline JWKS for offline verification
expectedAudiencestring | string[]Resource URLRequired audience claim value(s)
requiredScopesstring[][]Scopes that must be present in token
allowAnonymousbooleanfalseAllow requests without tokens

Provider Examples

@FrontMcp({
  info: { name: 'MyServer', version: '1.0.0' },
  auth: {
    mode: 'transparent',
    provider: 'https://your-tenant.auth0.com',
    // JWKS auto-discovered from /.well-known/jwks.json
    expectedAudience: 'https://api.yourservice.com',
    requiredScopes: ['openid', 'profile'],
  },
})
export class Server {}

Token Flow


Orchestrated Remote Mode

FrontMCP acts as an OAuth server while proxying user authentication to a single mandatory upstream IdP.
@FrontMcp({
  info: { name: 'MyServer', version: '1.0.0' },
  auth: {
    mode: 'remote',
    provider: 'https://auth.example.com',
    clientId: 'your-client-id',
    clientSecret: 'your-client-secret',
    scopes: ['openid', 'profile', 'email'],
    consent: { enabled: true },
  },
})
export class Server {}
In mode: 'remote', GET /oauth/authorize redirects straight to the upstream IdP — FrontMCP never shows its own login page or a provider-selection page. After the IdP returns to /oauth/provider/{id}/callback, FrontMCP exchanges the code, stores the upstream tokens (encrypted, server-side), derives the session identity (sub/email/name) from the upstream user, and mints its own HS256-signed session token. Tools read the upstream token with this.orchestration.getToken('<provider-id>') — the provider id is taken from providerConfig.id (or derived from the provider hostname).

Configuration Options

OptionTypeDefaultDescription
providerstringRequiredUpstream IdP base URL
clientIdstringRequiredOAuth client ID
clientSecretstring-OAuth client secret (confidential clients)
scopesstring[]['openid']Scopes to request from IdP
providerConfig.dcrEnabledbooleanfalseUse Dynamic Client Registration
consentConsentConfig{ enabled: false }Show consent UI after IdP login

When to Use Orchestrated Remote

Multiple identity providers - Federate users from different IdPs under one session
Progressive authorization - Users authorize apps incrementally
Custom token claims - Add claims not available from upstream
Consent UI - Let users select which tools/resources to grant

Token Flow


Dynamic Client Registration

Not yet wired. providerConfig.dcrEnabled / providerConfig.registrationEndpoint are accepted by the schema but FrontMCP does not yet perform upstream Dynamic Client Registration. In mode: 'remote' you must provide a pre-registered clientId (and clientSecret for confidential clients) — without a clientId the upstream provider is not registered and /oauth/authorize returns a configuration error. DCR support is planned; track it before relying on it.
auth: {
  mode: 'remote',
  provider: 'https://auth.example.com',
  clientId: 'pre-registered-client-id', // required today (DCR not yet wired)
  clientSecret: process.env.IDP_CLIENT_SECRET,
}

Endpoint Overrides

Override auto-discovered endpoints for non-standard IdPs:
auth: {
  mode: 'remote',
  provider: 'https://legacy-idp.example.com',
  providerConfig: {
    authEndpoint: 'https://legacy-idp.example.com/auth',
    tokenEndpoint: 'https://legacy-idp.example.com/token',
    userInfoEndpoint: 'https://legacy-idp.example.com/userinfo',
    jwksUri: 'https://legacy-idp.example.com/keys',
  },
}

Inline JWKS

For offline verification or non-discoverable providers:
auth: {
  mode: 'transparent',
  provider: 'https://auth.example.com',
  providerConfig: {
    jwks: {
      keys: [
        {
          kty: 'RSA',
          kid: 'key-id-1',
          alg: 'RS256',
          n: '...',
          e: 'AQAB',
        },
      ],
    },
  },
}

Multi-Provider Setup

Combine multiple providers with orchestrated mode:
@App({
  name: 'Slack',
  auth: {
    mode: 'transparent',
    provider: 'https://slack.com/oauth',
  },
  standalone: true,
})
export class SlackApp {}

@App({
  name: 'CRM',
  auth: {
    mode: 'transparent',
    provider: 'https://company.auth0.com',
  },
})
export class CrmApp {}

@FrontMcp({
  info: { name: 'Suite', version: '1.0.0' },
  apps: [SlackApp, CrmApp],
  auth: {
    mode: 'local',
    consent: { enabled: true },
  },
})
export class Server {}

Per-App Remote Auth

Configure different providers per app:
@App({
  name: 'Billing',
  auth: {
    mode: 'transparent',
    provider: 'https://billing.auth0.com',
  },
})
export class BillingApp {}

@App({
  name: 'Analytics',
  auth: {
    mode: 'transparent',
    provider: 'https://analytics.okta.com/oauth2/default',
  },
})
export class AnalyticsApp {}

@FrontMcp({
  info: { name: 'Suite', version: '1.0.0' },
  apps: [BillingApp, AnalyticsApp],
  splitByApp: true,
})
export class Server {}
Use standalone: true to expose an app’s OAuth endpoints directly, bypassing the parent auth.

Troubleshooting

  • Check expectedAudience matches the token’s aud claim
  • Verify JWKS endpoint is accessible
  • Ensure token hasn’t expired
  • Verify IdP URL is correct
  • Check network connectivity
  • Try providing inline JWKS via providerConfig.jwks
  • Register exact redirect URI with IdP
  • Check for trailing slashes
  • Ensure protocol (http/https) matches

Next Steps

Remote Proxy

Handle IdPs without DCR support

Progressive Authorization

Implement incremental app authorization

Local OAuth

Built-in OAuth server setup

Production Checklist

Security requirements for deployment