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',
    remote: {
      provider: 'https://auth.example.com',
    },
    expectedAudience: 'https://api.myservice.com',
  },
})
export class Server {}

Configuration Options

OptionTypeDefaultDescription
remote.providerstringRequiredBase URL of the identity provider
remote.jwksUristringAuto-discoveredCustom JWKS endpoint
remote.jwksJSONWebKeySet-Inline JWKS for offline verification
expectedAudiencestring | string[]Issuer 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',
    remote: {
      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 upstream IdP.
@FrontMcp({
  info: { name: 'MyServer', version: '1.0.0' },
  auth: {
    mode: 'orchestrated',
    type: 'remote',
    remote: {
      provider: 'https://auth.example.com',
      clientId: 'your-client-id',
      clientSecret: 'your-client-secret',
      scopes: ['openid', 'profile', 'email'],
    },
    consent: { enabled: true },
    sessionMode: 'stateful',
  },
})
export class Server {}

Configuration Options

OptionTypeDefaultDescription
remote.providerstringRequiredUpstream IdP base URL
remote.clientIdstringRequiredOAuth client ID
remote.clientSecretstring-OAuth client secret (confidential clients)
remote.scopesstring[]['openid']Scopes to request from IdP
remote.dcrEnabledbooleanfalseUse Dynamic Client Registration
consentbooleanfalseShow consent UI after IdP login
sessionMode'stateful' | 'stateless''stateful'Session management strategy

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

When the IdP supports DCR, FrontMCP can register clients automatically:
auth: {
  mode: 'orchestrated',
  type: 'remote',
  remote: {
    provider: 'https://auth.example.com',
    dcrEnabled: true, // Enable DCR
    // clientId/clientSecret derived from registration
  },
}
Not all providers support DCR. Check your IdP documentation.

Endpoint Overrides

Override auto-discovered endpoints for non-standard IdPs:
auth: {
  mode: 'orchestrated',
  type: 'remote',
  remote: {
    provider: 'https://legacy-idp.example.com',
    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',
  remote: {
    provider: 'https://auth.example.com',
    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',
    remote: { provider: 'https://slack.com/oauth' },
  },
  standalone: true,
})
export class SlackApp {}

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

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

Per-App Remote Auth

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

@App({
  name: 'Analytics',
  auth: {
    mode: 'transparent',
    remote: {
      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 remote.jwks
  • Register exact redirect URI with IdP
  • Check for trailing slashes
  • Ensure protocol (http/https) matches

Next Steps