> ## Documentation Index
> Fetch the complete documentation index at: https://docs.agentfront.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Authorization Modes

> Deep dive into public, transparent, local, and remote authentication modes

FrontMCP's four authentication modes address different deployment scenarios. Understanding when to use each mode is critical for both security and developer experience.

## Mode Overview

The `auth.mode` literal accepts one of four values: `'public'`, `'transparent'`, `'local'`, `'remote'`.

```mermaid theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
graph TB
    subgraph "Authentication Modes"
        Public["mode: 'public'<br/>Anonymous Access"]
        Transparent["mode: 'transparent'<br/>Pass-through Tokens"]
        Local["mode: 'local'<br/>Built-in OAuth Server"]
        Remote["mode: 'remote'<br/>OAuth Server proxying to upstream IdP"]
    end
```

## Mode Comparison

| Feature            | Public         | Transparent       | Local                 | Remote                |
| ------------------ | -------------- | ----------------- | --------------------- | --------------------- |
| Token Required     | No             | Yes (external)    | Yes (FrontMCP-issued) | Yes (FrontMCP-issued) |
| User Identity      | Anonymous      | From upstream IdP | From login form       | From upstream IdP     |
| JWKS Source        | Self-generated | Upstream IdP      | Self-generated        | Self-generated        |
| Session Management | Minimal        | Pass-through      | Full control          | Full control          |
| Multi-provider     | No             | Single provider   | Multiple via apps     | Multiple via apps     |
| Progressive Auth   | No             | No                | Yes                   | Yes                   |
| Consent UI         | No             | No                | Optional              | Optional              |

***

## Public Mode

No authentication required. All requests receive an anonymous session.

```typescript theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
const auth: AuthOptionsInput = {
  mode: 'public',
  sessionTtl: 3600, // 1 hour
  anonymousScopes: ['anonymous'],
};
```

### How It Works

```mermaid theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
sequenceDiagram
    participant Client
    participant FrontMCP

    Client->>FrontMCP: Request without token
    FrontMCP->>FrontMCP: Generate anonymous JWT
    FrontMCP-->>Client: Response + anonymous session
```

### Configuration Options

| Option                   | Type                | Default         | Description                           |
| ------------------------ | ------------------- | --------------- | ------------------------------------- |
| `sessionTtl`             | `number`            | `3600`          | Session lifetime in seconds           |
| `anonymousScopes`        | `string[]`          | `['anonymous']` | Scopes assigned to anonymous sessions |
| `publicAccess.tools`     | `string[] \| 'all'` | `'all'`         | Tools accessible without auth         |
| `publicAccess.prompts`   | `string[] \| 'all'` | `'all'`         | Prompts accessible without auth       |
| `publicAccess.rateLimit` | `number`            | `60`            | Rate limit per IP per minute          |

### Use Cases

<CardGroup cols={2}>
  <Card title="Development" icon="code">
    Rapid prototyping without auth setup overhead
  </Card>

  <Card title="Public APIs" icon="globe">
    Endpoints that don't require user identity
  </Card>
</CardGroup>

<Warning>
  **Do NOT use public mode when you need:**

  * User identity tracking
  * Audit trails
  * Access control per user
  * Compliance requirements
</Warning>

***

## Transparent Mode

Pass-through tokens from an external identity provider. FrontMCP validates tokens but doesn't issue them.

```typescript theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
const auth: AuthOptionsInput = {
  mode: 'transparent',
  provider: 'https://auth.example.com',
  providerConfig: {
    jwksUri: 'https://auth.example.com/.well-known/jwks.json',
  },
  expectedAudience: 'https://api.myservice.com',
  requiredScopes: ['openid'],
  allowAnonymous: false,
};
```

### How It Works

```mermaid theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
sequenceDiagram
    participant Client
    participant FrontMCP
    participant IdP as Identity Provider

    Client->>IdP: Authenticate
    IdP-->>Client: Access Token (JWT)
    Client->>FrontMCP: Request + Bearer token
    FrontMCP->>IdP: Fetch JWKS (cached)
    FrontMCP->>FrontMCP: Verify JWT signature
    FrontMCP->>FrontMCP: Validate claims (aud, exp, scopes)
    FrontMCP-->>Client: Authorized response
```

### Configuration Options

| Option                   | Type                 | Default         | Description                                                             |
| ------------------------ | -------------------- | --------------- | ----------------------------------------------------------------------- |
| `provider`               | `string`             | Required        | Base URL of the IdP                                                     |
| `providerConfig.jwksUri` | `string`             | Auto-discovered | Custom JWKS endpoint                                                    |
| `providerConfig.jwks`    | `JSONWebKeySet`      | -               | Inline JWKS for offline verification                                    |
| `expectedAudience`       | `string \| string[]` | Required        | Required audience claim value(s) — typically the protected resource URL |
| `requiredScopes`         | `string[]`           | `[]`            | Scopes that must be present                                             |
| `allowAnonymous`         | `boolean`            | `false`         | Allow requests without tokens                                           |

### Provider Examples

<Tabs>
  <Tab title="Auth0">
    ```typescript theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
    auth: {
      mode: 'transparent',
      provider: 'https://your-tenant.auth0.com',
      // JWKS discovered automatically from /.well-known/jwks.json
      expectedAudience: 'https://api.yourservice.com',
    }
    ```
  </Tab>

  <Tab title="Okta">
    ```typescript theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
    auth: {
      mode: 'transparent',
      provider: 'https://your-org.okta.com/oauth2/default',
      expectedAudience: 'api://default',
    }
    ```
  </Tab>

  <Tab title="Azure AD">
    ```typescript theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
    auth: {
      mode: 'transparent',
      provider: 'https://login.microsoftonline.com/{tenant}/v2.0',
      providerConfig: {
        jwksUri: 'https://login.microsoftonline.com/{tenant}/discovery/v2.0/keys',
      },
      expectedAudience: 'api://{client-id}',
    }
    ```
  </Tab>
</Tabs>

### Use Cases

<CardGroup cols={2}>
  <Card title="Existing IdP Integration" icon="plug">
    Your organization already uses Auth0, Okta, or similar
  </Card>

  <Card title="Single Provider" icon="1">
    All users authenticate through one identity provider
  </Card>
</CardGroup>

<Warning>
  **Do NOT use transparent mode when you need:**

  * Multiple identity providers
  * Progressive authorization (add apps over time)
  * Server-side token storage with silent refresh
  * Custom token claims
</Warning>

***

## Local Mode

FrontMCP acts as a full OAuth 2.1 authorization server with a built-in login form. Self-contained auth server with built-in user management.

```typescript theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
const auth: AuthOptionsInput = {
  mode: 'local',
  consent: { enabled: true },
  tokenStorage: 'memory', // Use { redis: ... } in production
};
```

<Warning>
  The built-in login page accepts any email format without validation. Replace with a real identity provider for production use.
</Warning>

## Remote Mode

FrontMCP acts as an OAuth 2.1 authorization server that **proxies user authentication to an upstream IdP**. End users never submit credentials to FrontMCP directly — they're redirected to the upstream IdP, and FrontMCP exchanges the resulting upstream code/tokens before issuing its own session token to the MCP client.

```typescript theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
const auth: AuthOptionsInput = {
  mode: 'remote',
  provider: 'https://auth.example.com',
  clientId: 'your-client-id',
  clientSecret: 'your-client-secret',
  scopes: ['openid', 'profile', 'email'],
  consent: { enabled: true },
};
```

### How It Works

```mermaid theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
sequenceDiagram
    participant User
    participant Client
    participant FrontMCP as FrontMCP Auth Server
    participant IdP as Upstream IdP
    participant Store as Authorization Store

    Note over Client: Generate PKCE<br/>code_verifier & code_challenge

    Client->>FrontMCP: GET /oauth/authorize<br/>response_type=code<br/>client_id, redirect_uri<br/>code_challenge (S256)<br/>scope, state

    FrontMCP->>Store: Store pending authorization
    FrontMCP-->>User: 302 Redirect to upstream IdP<br/>(authorize URL + upstream PKCE)

    User->>IdP: Authenticate (credentials, MFA, …)
    IdP-->>FrontMCP: Redirect back with upstream auth code
    FrontMCP->>IdP: POST /token (exchange upstream code)
    IdP-->>FrontMCP: { id_token, access_token, refresh_token }

    FrontMCP->>Store: Create FrontMCP authorization code<br/>(60s TTL, single-use)
    FrontMCP-->>Client: Redirect to redirect_uri<br/>?code=xxx&state=yyy

    Client->>FrontMCP: POST /oauth/token<br/>grant_type=authorization_code<br/>code, redirect_uri<br/>client_id, code_verifier

    FrontMCP->>Store: Get & validate code
    FrontMCP->>FrontMCP: Verify PKCE<br/>SHA256(code_verifier) == code_challenge
    FrontMCP->>Store: Mark code as used
    FrontMCP->>FrontMCP: Sign FrontMCP session token (JWT)<br/>using identity from upstream id_token
    FrontMCP->>Store: Store refresh token (links to upstream tokens)
    FrontMCP-->>Client: { access_token, refresh_token, expires_in }
```

### Configuration Options

| Option               | Type                                 | Default              | Description                     |
| -------------------- | ------------------------------------ | -------------------- | ------------------------------- |
| `consent`            | `ConsentConfig`                      | `{ enabled: false }` | Consent UI configuration        |
| `tokenStorage`       | `'memory' \| { redis: RedisConfig }` | `'memory'`           | Storage backend                 |
| `allowDefaultPublic` | `boolean`                            | `false`              | Allow unauthenticated requests  |
| `federatedAuth`      | `FederatedAuthConfig`                | -                    | Federated auth state validation |
| `incrementalAuth`    | `IncrementalAuthConfig`              | `{ enabled: true }`  | Progressive authorization       |

### Consent Configuration

```typescript theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
consent: {
  enabled: true,
  groupByApp: true,           // Group tools by app in UI
  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
}
```

### Incremental Authorization

```typescript theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
incrementalAuth: {
  enabled: true,
  allowSkip: true,                    // Allow skipping app auth
  showAllAppsAtOnce: true,            // Show all apps in one page
  skippedAppBehavior: 'require-auth', // 'anonymous' or 'require-auth'
}
```

### Federated Authentication Configuration

Configure how state parameters are validated during federated (multi-provider) authentication flows.

```typescript theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
federatedAuth: {
  stateValidation: 'strict',  // 'strict' (recommended) or 'format'
}
```

| Option            | Values                 | Description                                                                         |
| ----------------- | ---------------------- | ----------------------------------------------------------------------------------- |
| `stateValidation` | `'strict' \| 'format'` | `'strict'`: Full state match (recommended). `'format'`: Only validates state format |

### OAuth Endpoints

Local and remote modes expose standard OAuth endpoints:

| Endpoint                                  | Method | Description                 |
| ----------------------------------------- | ------ | --------------------------- |
| `/oauth/authorize`                        | GET    | Start authorization flow    |
| `/oauth/token`                            | POST   | Exchange code for tokens    |
| `/oauth/register`                         | POST   | Dynamic Client Registration |
| `/oauth/userinfo`                         | GET    | User profile information    |
| `/.well-known/oauth-authorization-server` | GET    | Server metadata             |
| `/.well-known/jwks.json`                  | GET    | Public signing keys         |

### Use Cases

<CardGroup cols={2}>
  <Card title="Multi-Provider Federation" icon="object-group">
    Combine multiple IdPs under one session (Slack + GitHub + custom)
  </Card>

  <Card title="Progressive Authorization" icon="chart-line">
    Users authorize apps incrementally as needed
  </Card>

  <Card title="Full Token Control" icon="sliders">
    Custom token lifetimes, scopes, and refresh behavior
  </Card>

  <Card title="Built-in Consent UI" icon="list-check">
    Let users choose which tools/resources to grant
  </Card>
</CardGroup>

<Warning>
  **Do NOT use `local` or `remote` mode when:**

  * You only have one IdP and don't need federation (use `transparent` instead)
  * You want to minimize auth complexity
  * Running multiple instances without Redis
</Warning>

***

## Mode Selection Flowchart

```mermaid theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
graph TD
    A[Start] --> B{Need user identity?}
    B -->|No| C[Public Mode]
    B -->|Yes| D{Multiple providers?}
    D -->|No| E{Need progressive auth<br/>or consent UI?}
    D -->|Yes| F[Local/Remote Mode]
    E -->|No| G[Transparent Mode]
    E -->|Yes| F
    F --> H{Have upstream IdP?}
    H -->|Yes| I[Remote Mode]
    H -->|No| J[Local Mode]
```

***

## Security Comparison

| Security Aspect        | Public         | Transparent           | Local              | Remote                                            |
| ---------------------- | -------------- | --------------------- | ------------------ | ------------------------------------------------- |
| Token Verification     | None           | Against upstream JWKS | Against local JWKS | Against local JWKS (FrontMCP-issued session)      |
| PKCE Support           | N/A            | Depends on IdP        | Always S256        | Always S256 (downstream); upstream depends on IdP |
| Refresh Token Rotation | N/A            | Depends on IdP        | Always rotated     | Depends on upstream IdP                           |
| Key Management         | Auto-generated | Upstream-managed      | Self-managed       | Self-managed (session JWKS) + upstream JWKS       |
| Consent UI             | No             | No                    | Optional           | Optional                                          |
| Session Revocation     | N/A            | N/A                   | Supported          | Supported                                         |

***

## Token Verification Flow

```mermaid theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
sequenceDiagram
    participant Client
    participant FrontMCP
    participant JwksService

    Client->>FrontMCP: Request + Bearer token

    alt Public/Local/Remote Mode
        FrontMCP->>JwksService: Get gateway JWKS
        FrontMCP->>FrontMCP: Verify JWT locally
    else Transparent Mode
        FrontMCP->>JwksService: Get provider JWKS (cached)
        Note over JwksService: Fetch from jwksUri or<br/>discover via .well-known
        FrontMCP->>FrontMCP: Verify JWT against provider
    end

    alt Valid Token
        FrontMCP->>FrontMCP: Extract claims (sub, scopes, etc.)
        FrontMCP-->>Client: Authorized response
    else Invalid Token
        FrontMCP-->>Client: 401 Unauthorized<br/>WWW-Authenticate header
    end
```

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Remote OAuth" icon="cloud" href="/frontmcp/authentication/remote">
    Configure upstream IdP integration
  </Card>

  <Card title="Local OAuth" icon="server" href="/frontmcp/authentication/local">
    Set up self-contained authentication
  </Card>

  <Card title="Progressive Authorization" icon="forward" href="/frontmcp/authentication/progressive">
    Implement incremental app authorization
  </Card>

  <Card title="Production Deployment" icon="rocket" href="/frontmcp/authentication/production">
    Security checklist for production
  </Card>
</CardGroup>
