IAuthService Contract
Reference for the Auth Service contract — authentication, session verification, user resolution, and logout
IAuthService Contract
The Auth Service handles authentication — verifying user identity through credentials, tokens, or external providers. It does not handle authorization (permissions); that is governed separately by the security layer (PermissionSets, sharing rules) in plugin-security.
Source: packages/spec/src/contracts/auth-service.ts
Service token: 'auth' (the CoreServiceName value; resolve with ctx.getService('auth'))
Interface Definition
export interface IAuthService {
/** Handle an incoming HTTP authentication request (login, callback, etc.). */
handleRequest(request: Request): Promise<Response>;
/** Verify a bearer token or session identifier and return the result. */
verify(token: string): Promise<AuthResult>;
/** Invalidate a session (logout). Optional. */
logout?(sessionId: string): Promise<void>;
/** Resolve the current user from a request. Optional. */
getCurrentUser?(request: Request): Promise<AuthUser | undefined>;
/** The session API, when the provider mounts it directly (legacy shape). Optional. */
api?: AuthSessionApi;
/** Resolve the session API, creating the auth instance on first use. Optional. */
getApi?(): Promise<AuthSessionApi | undefined>;
/** Whether this deployment's auth gate is live. Optional. */
isAuthGateActive?(): boolean;
/** Verify an OAuth 2.1 access token from the embedded AS (MCP surface). Optional. */
verifyMcpAccessToken?(token: string): Promise<{ userId: string; scopes: string[]; clientId?: string } | undefined>;
/** The MCP resource identifier (RFC 8707 `resource` / token `aud`). Optional. */
getMcpResourceUrl?(): string;
/** RFC 9728 protected-resource metadata URL, or `null` when OAuth is off. Optional. */
getMcpResourceMetadataUrl?(): string | null;
}The two required members are the core: it follows the Dependency Inversion Principle so that plugins depend on the contract rather than a concrete provider. Concrete implementations (better-auth, custom, LDAP, etc.) supply the actual logic, and handleRequest works directly with the standard Request/Response types.
Everything after verify is optional, and each optional member describes a capability a provider may or may not have — a caller must probe before use. Two pairs are worth reading together:
apiandgetApi()are the same session handle by two routes.apiis the legacy direct mount;getApi()is the lazy accessor, and it is the one to prefer — the shippedplugin-authregisters anAuthManager, which has noapimember at all, so a caller that reads onlyapigetsundefinedon every current deployment. Readapi ?? await getApi?.().getMcpResourceUrl()andgetMcpResourceMetadataUrl()both describe the MCP OAuth surface; the second returnsnull(rather than being absent) when the OAuth track is off for the deployment.
Core Authentication
handleRequest
The HTTP entry point for authentication. It receives a standard Request (login, OAuth callback, etc.) and returns a standard Response. The concrete implementation owns route handling, credential parsing, and cookie/token issuance.
// Wire the auth service into an HTTP handler
const response = await authService.handleRequest(request);
return response;verify
Validates a bearer token or session identifier and returns an AuthResult. On success the result carries user and session; on failure success is false and error holds a message.
const result = await authService.verify(accessToken);
if (!result.success) {
throw new Error(result.error ?? 'Invalid or expired token');
}
console.log(result.user?.email); // "jane@example.com"logout
Invalidates a session by its identifier. This method is optional on the contract.
await authService.logout?.(session.id);AuthUser Interface
The AuthUser object represents an authenticated user throughout the system.
export interface AuthUser {
/** User identifier */
id: string;
/** Email address */
email: string;
/** Display name */
name: string;
/** Assigned position identifiers */
positions?: string[];
/** Current tenant identifier (multi-tenant) */
tenantId?: string;
}| Property | Type | Description |
|---|---|---|
id | string | Unique user identifier |
email | string | User's email address |
name | string | Display name |
positions | string[]? | Assigned position identifiers |
tenantId | string? | Current tenant identifier (multi-tenant) |
User Resolution
getCurrentUser
Resolves the authenticated user from a request. Returns undefined when the request is unauthenticated. This method is optional on the contract.
const user = await authService.getCurrentUser?.(request);
if (user) {
console.log(`Request from ${user.name} (${user.positions?.join(', ')})`);
}AuthSession Interface
export interface AuthSession {
/** Session identifier */
id: string;
/** Associated user identifier */
userId: string;
/** Session expiry (ISO 8601) */
expiresAt: string;
/** Bearer token (if not using cookies) */
token?: string;
}AuthResult
verify resolves to an AuthResult. On success it carries the user and session; on failure error holds a message string.
export interface AuthResult {
/** Whether authentication succeeded */
success: boolean;
/** Authenticated user (if success) */
user?: AuthUser;
/** Active session (if success) */
session?: AuthSession;
/** Error message (if failure) */
error?: string;
}