---
title: "AuthRegistry"
description: "The AuthRegistry manages authentication providers within a scope. It handles auth configuration, provider detection, and orchestration."
icon: "lock"
keywords: ['frontmcp', 'mcp', 'model context protocol', 'sdk', 'reference', 'api', 'registry', 'registries', 'auth', 'typescript']
---

## Overview

```typescript
import { AuthRegistry } from '@frontmcp/sdk';

// Access via scope
const auth = scope.authProviders;

// Get primary auth provider
const primary = auth.getPrimary();

// Get all auth providers
const providers = auth.getAuthProviders();
```

## Methods

### getPrimary()

Get the primary auth provider.

```typescript
getPrimary(): FrontMcpAuth
```

**Example:**

```typescript
const auth = registry.getPrimary();

// Provider identity / mode-derived metadata
console.log(auth.id);        // e.g. 'github_com'
console.log(auth.issuer);    // OAuth issuer URL when applicable

// Validate an incoming HTTP request (throws on failure)
await auth.validate(serverRequest);

// Authenticated outbound fetch through the active provider
const res = await auth.fetch('https://api.example.com/me');
```

### getAuthProviders()

Get all auth provider entries.

```typescript
getAuthProviders(): ReadonlyArray<AuthProviderEntry>
```

**Example:**

```typescript
const providers = registry.getAuthProviders();
for (const provider of providers) {
  console.log(`Provider: ${provider.name} (${provider.mode})`);
}
```

## Auth Modes

FrontMCP supports four authentication modes:

<CardGroup cols={2}>
  <Card title="Public" icon="globe">
    `mode: 'public'` — no authentication
  </Card>
  <Card title="Transparent" icon="eye">
    `mode: 'transparent'` — pass-through tokens validated against upstream JWKS
  </Card>
  <Card title="Local" icon="server">
    `mode: 'local'` — built-in OAuth 2.1 authorization server
  </Card>
  <Card title="Remote" icon="sitemap">
    `mode: 'remote'` — OAuth 2.1 server proxying to an upstream IdP
  </Card>
</CardGroup>

See the [Authentication overview](/frontmcp/authentication/overview) for full mode semantics. The registry exposes `requiresOrchestration` (true for `local`/`remote`) so adapters know whether to mount OAuth routes.

## Properties

### requiresOrchestration

Whether the current configuration requires orchestration.

```typescript
if (registry.requiresOrchestration) {
  // Setup OAuth callbacks, session management, etc.
}
```

### detection

Auth provider detection result across apps in scope.

```typescript
interface AuthProviderDetectionResult {
  /** Map of providerId -> DetectedAuthProvider (mode, scopes, appIds, etc.) */
  providers: Map<string, DetectedAuthProvider>;
  /** True when local/remote mode requires the OAuth orchestration routes */
  requiresOrchestration: boolean;
  /** Provider id at the parent scope (if any) */
  parentProviderId?: string;
  /** Provider ids contributed only by child apps */
  childProviderIds: string[];
  /** Number of distinct providers */
  uniqueProviderCount: number;
  /** Configuration validation errors */
  validationErrors: string[];
  /** Non-fatal warnings */
  warnings: string[];
}
```

## Auth Provider Detection

The registry detects auth requirements across the scope hierarchy:

```typescript
// Check detection result
const detection = registry.detection;

if (detection.uniqueProviderCount > 0) {
  for (const [id, provider] of detection.providers) {
    console.log(`${id}: mode=${provider.mode} apps=[${provider.appIds.join(', ')}]`);
  }
}

if (registry.requiresOrchestration) {
  // Mount OAuth routes
}
```

## Auth in Context Classes

Context classes that extend `ExecutionContextBase` expose two auth surfaces:

```typescript
@Tool({ name: 'protected_tool', inputSchema: {} })
class ProtectedTool extends ToolContext {
  async execute() {
    // Typed FrontMcpAuthContext (roles, permissions, claims, scopes)
    if (!this.auth.hasRole('admin')) throw new Error('Admin required');
    const tenantId = this.auth.claims['tenantId'];

    // Raw token (Partial<AuthInfo>) for outbound API calls
    const token = this.context.authInfo?.token;
  }
}
```

## Configuration Validation

The registry validates auth configuration:

```typescript
// Invalid configuration throws
@FrontMcp({
  auth: {
    mode: 'local',
    providers: [], // Error: No providers specified
  },
})
class InvalidServer { }
```

## FrontMcpAuth API

The primary auth provider is an abstract base class:

```typescript
abstract class FrontMcpAuth<Options extends AuthOptions = AuthOptions> {
  /** Promise resolved when the provider has finished initializing. */
  ready: Promise<void>;
  /** Parsed auth options (mode, providers, etc.). */
  readonly options: Options;
  /** Stable provider ID derived from options. */
  readonly id: string;

  /** Authenticated outbound fetch (mode-specific implementation). */
  abstract fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;

  /** Validate an incoming server request — throws if not authenticated. */
  abstract validate(request: ServerRequest): Promise<void>;

  /** OAuth issuer URL (when applicable). */
  abstract get issuer(): string;
}
```

For request-scoped role/permission/scope checks, use `this.auth` (a
`FrontMcpAuthContext`) inside execution contexts — see the section below.

## Session Integration

Auth integrates with session management:

```typescript
@FrontMcp({
  auth: {
    mode: 'local',
    sessionStore: {
      provider: 'redis',
      host: 'localhost',
      keyPrefix: 'auth:session:',
    },
  },
})
class SecureServer { }
```

## Multi-App Auth

When multiple apps have different auth requirements:

```typescript
@FrontMcp({
  name: 'server',
  apps: [PublicApp, ProtectedApp],
})
class MultiAuthServer { }

// The registry detects mixed auth providers across nested apps
const detection = scope.authProviders.detection;
// detection.providers is a Map<string, DetectedAuthProvider>
const providerIds = Array.from(detection.providers.keys());
// e.g. ['public', 'auth_example_com']
for (const provider of detection.providers.values()) {
  // provider.mode is one of 'public' | 'transparent' | 'local' | 'remote'
  console.log(`${provider.id} -> ${provider.mode} (apps=[${provider.appIds.join(', ')}])`);
}
```

## FrontMcpAuthContext

The `FrontMcpAuthContext` is a request-scoped auth identity object available inside tool, resource, and prompt execution. It provides role, permission, and scope checks extracted from JWT claims.

```typescript
import type { FrontMcpAuthContext } from '@frontmcp/auth';
```

### Properties

| Property        | Type                                  | Description                                                  |
| --------------- | ------------------------------------- | ------------------------------------------------------------ |
| `user`          | `FrontMcpAuthUser`                    | Resolved user identity (`sub`, `name`, `email`, `picture`)   |
| `isAnonymous`   | `boolean`                             | True when `sub` starts with `anon:` or is empty              |
| `mode`          | `string`                              | Authentication mode (`public`, `transparent`, `local`, `remote`) |
| `sessionId`     | `string`                              | Session identifier (empty string if no session)              |
| `scopes`        | `readonly string[]`                   | OAuth scopes granted to this session                         |
| `claims`        | `Readonly<Record<string, unknown>>`   | Raw JWT claims                                               |
| `roles`         | `readonly string[]`                   | Resolved roles (via `claimsMapping` or direct extraction)    |
| `permissions`   | `readonly string[]`                   | Resolved permissions (via `claimsMapping` or direct)         |

### Methods

| Method               | Signature                                      | Description                                  |
| -------------------- | ---------------------------------------------- | -------------------------------------------- |
| `hasRole`            | `(role: string) => boolean`                    | Check if user has a specific role             |
| `hasAllRoles`        | `(roles: readonly string[]) => boolean`        | Check if user has ALL specified roles         |
| `hasAnyRole`         | `(roles: readonly string[]) => boolean`        | Check if user has at least one role           |
| `hasPermission`      | `(permission: string) => boolean`              | Check if user has a specific permission       |
| `hasAllPermissions`  | `(permissions: readonly string[]) => boolean`  | Check if user has ALL specified permissions   |
| `hasAnyPermission`   | `(permissions: readonly string[]) => boolean`  | Check if user has at least one permission     |
| `hasScope`           | `(scope: string) => boolean`                   | Check if session has a specific OAuth scope   |
| `hasAllScopes`       | `(scopes: readonly string[]) => boolean`       | Check if session has ALL specified scopes     |
| `hasAnyScope`        | `(scopes: readonly string[]) => boolean`       | Check if session has at least one scope       |

### Extension

Add custom typed fields via global interface augmentation:

```typescript
declare global {
  interface ExtendFrontMcpAuthContext {
    tenantId: string;
    orgName: string;
  }
}
```

Custom fields are populated by `AuthContextPipe` functions registered in your server config.

<Info>
  **FrontMcpAuthContext vs Authorization**: `FrontMcpAuthContext` is request-scoped and provides roles, permissions, and scopes from JWT claims. The `Authorization` interface is transport-scoped and tracks authorized tools, prompts, apps, and provider tokens. Use `FrontMcpAuthContext` for role/permission checks; use `Authorization` for tool/app access control.
</Info>

## Related

- [Authentication Overview](/frontmcp/authentication/overview)
- [Auth Modes](/frontmcp/authentication/modes)
- [Authorities](/frontmcp/authentication/authorities)
- [Production Auth](/frontmcp/authentication/production)
- [Registries Overview](/frontmcp/sdk-reference/registries/overview)
