Skip to content

TypeScript Types

OAuth Callback is fully typed with TypeScript, providing comprehensive type safety and excellent IDE support. This page documents all exported types and interfaces available in the library.

Type Organization

Core Types

GetAuthCodeOptions

Configuration options for the getAuthCode function.

typescript
interface GetAuthCodeOptions {
  authorizationUrl: string; // OAuth authorization URL
  port?: number; // Server port (default: 3000)
  hostname?: string; // Hostname (default: "localhost")
  callbackPath?: string; // Callback path (default: "/callback")
  timeout?: number; // Timeout in ms (default: 30000)
  launch?: (url: string) => unknown; // Optional URL launcher
  successHtml?: string; // Custom success HTML
  errorHtml?: string; // Custom error HTML template
  signal?: AbortSignal; // Cancellation signal
  onRequest?: (req: Request) => void; // Request callback
}

Usage Example

typescript
import type { GetAuthCodeOptions } from "oauth-callback";

const options: GetAuthCodeOptions = {
  authorizationUrl: "https://oauth.example.com/authorize?...",
  port: 8080,
  timeout: 60000,
  successHtml: "<h1>Success!</h1>",
  errorHtml: "<h1>Error: {{error_description}}</h1>",
  onRequest: (req) => console.log(`Request: ${req.url}`),
};

const result = await getAuthCode(options);

CallbackResult

Result object returned from OAuth callback containing authorization code or error details.

typescript
interface CallbackResult {
  code?: string; // Authorization code
  state?: string; // State parameter for CSRF
  error?: string; // OAuth error code
  error_description?: string; // Error description
  error_uri?: string; // Error info URI
  [key: string]: string | undefined; // Additional params
}

Usage Example

typescript
import type { CallbackResult } from "oauth-callback";

function handleCallback(result: CallbackResult) {
  if (result.error) {
    console.error(`OAuth error: ${result.error}`);
    if (result.error_description) {
      console.error(`Details: ${result.error_description}`);
    }
    return;
  }

  if (result.code) {
    console.log(`Authorization code: ${result.code}`);

    // Validate state for CSRF protection
    if (result.state !== expectedState) {
      throw new Error("State mismatch - possible CSRF attack");
    }

    // Exchange code for tokens
    exchangeCodeForTokens(result.code);
  }
}

ServerOptions

Configuration options for the OAuth callback server.

typescript
interface ServerOptions {
  port: number; // Port to bind to
  hostname?: string; // Hostname (default: "localhost")
  successHtml?: string; // Custom success HTML
  errorHtml?: string; // Error HTML template
  signal?: AbortSignal; // Cancellation signal
  onRequest?: (req: Request) => void; // Request callback
}

Usage Example

typescript
import type { ServerOptions } from "oauth-callback";

const serverOptions: ServerOptions = {
  port: 3000,
  hostname: "127.0.0.1",
  successHtml: `
    <html>
      <body>
        <h1>Authorization successful!</h1>
        <script>window.close()</script>
      </body>
    </html>
  `,
  onRequest: (req) => {
    const url = new URL(req.url);
    console.log(`[${req.method}] ${url.pathname}`);
  },
};

CallbackServer

Interface for OAuth callback server implementations across different runtimes.

typescript
interface CallbackServer {
  start(options: ServerOptions): Promise<void>;
  waitForCallback(path: string, timeout: number): Promise<CallbackResult>;
  stop(): Promise<void>;
}

Implementation Example

typescript
import type {
  CallbackServer,
  ServerOptions,
  CallbackResult,
} from "oauth-callback";

class CustomCallbackServer implements CallbackServer {
  private server?: HttpServer;

  async start(options: ServerOptions): Promise<void> {
    // Start HTTP server
    this.server = await createServer(options);
  }

  async waitForCallback(
    path: string,
    timeout: number,
  ): Promise<CallbackResult> {
    // Wait for OAuth callback
    return new Promise((resolve, reject) => {
      const timer = setTimeout(() => {
        reject(new Error("Timeout waiting for callback"));
      }, timeout);

      this.server.on("request", (req) => {
        if (req.url.startsWith(path)) {
          clearTimeout(timer);
          const params = parseQueryParams(req.url);
          resolve(params);
        }
      });
    });
  }

  async stop(): Promise<void> {
    // Stop server
    await this.server?.close();
  }
}

Storage Types

TokenStore

Basic interface for OAuth token storage.

typescript
interface TokenStore {
  get(key: string): Promise<Tokens | null>;
  set(key: string, tokens: Tokens): Promise<void>;
  delete(key: string): Promise<void>;
}

Tokens

OAuth token data structure.

typescript
interface Tokens {
  accessToken: string; // OAuth access token
  refreshToken?: string; // Optional refresh token
  expiresAt?: number; // Absolute expiry (Unix ms)
  scope?: string; // Space-delimited scopes
}

Usage Example

typescript
import type { Tokens, TokenStore } from "oauth-callback/mcp";

class CustomTokenStore implements TokenStore {
  private storage = new Map<string, Tokens>();

  async get(key: string): Promise<Tokens | null> {
    return this.storage.get(key) ?? null;
  }

  async set(key: string, tokens: Tokens): Promise<void> {
    // Check if token is expired
    if (tokens.expiresAt && Date.now() >= tokens.expiresAt) {
      console.warn("Storing expired token");
    }
    this.storage.set(key, tokens);
  }

  async delete(key: string): Promise<void> {
    this.storage.delete(key);
  }
}

OAuthStore

Extended storage interface with Dynamic Client Registration and PKCE verifier persistence.

typescript
import { OAuthStoreBrand } from "oauth-callback/mcp";

interface OAuthStore extends TokenStore {
  readonly [OAuthStoreBrand]: true; // Required brand for type detection

  getClient(key: string): Promise<ClientInfo | null>;
  setClient(key: string, client: ClientInfo): Promise<void>;
  deleteClient(key: string): Promise<void>;

  getCodeVerifier(key: string): Promise<string | null>;
  setCodeVerifier(key: string, verifier: string): Promise<void>;
  deleteCodeVerifier(key: string): Promise<void>;
}

ClientInfo

Dynamic client registration data.

typescript
interface ClientInfo {
  clientId: string; // OAuth client ID
  clientSecret?: string; // Client secret
  clientIdIssuedAt?: number; // Registration time
  clientSecretExpiresAt?: number; // Secret expiry
}

Complete Storage Example

typescript
import {
  OAuthStoreBrand,
  type OAuthStore,
  type Tokens,
  type ClientInfo,
} from "oauth-callback/mcp";

class DatabaseOAuthStore implements OAuthStore {
  readonly [OAuthStoreBrand] = true as const;

  constructor(private db: Database) {}

  // TokenStore methods
  async get(key: string): Promise<Tokens | null> {
    return await this.db.tokens.findOne({ key });
  }

  async set(key: string, tokens: Tokens): Promise<void> {
    await this.db.tokens.upsert({ key }, tokens);
  }

  async delete(key: string): Promise<void> {
    await this.db.tokens.delete({ key });
  }

  // Client registration methods
  async getClient(key: string): Promise<ClientInfo | null> {
    return await this.db.clients.findOne({ key });
  }

  async setClient(key: string, client: ClientInfo): Promise<void> {
    await this.db.clients.upsert({ key }, client);
  }

  async deleteClient(key: string): Promise<void> {
    await this.db.clients.delete({ key });
  }

  // PKCE verifier methods
  async getCodeVerifier(key: string): Promise<string | null> {
    const doc = await this.db.verifiers.findOne({ key });
    return doc?.verifier ?? null;
  }

  async setCodeVerifier(key: string, verifier: string): Promise<void> {
    await this.db.verifiers.upsert({ key }, { verifier });
  }

  async deleteCodeVerifier(key: string): Promise<void> {
    await this.db.verifiers.delete({ key });
  }
}

MCP Types

BrowserAuthOptions

Configuration for browser-based OAuth flows with MCP servers.

typescript
interface BrowserAuthOptions {
  // OAuth credentials
  clientId?: string; // Pre-registered client ID
  clientSecret?: string; // Pre-registered secret
  scope?: string; // OAuth scopes

  // Server configuration
  port?: number; // Callback port (default: 3000)
  hostname?: string; // Hostname (default: "localhost")
  callbackPath?: string; // Path (default: "/callback")

  // Storage
  store?: TokenStore; // Token storage
  storeKey?: string; // Storage key for token isolation

  // Behavior
  launch?: (url: string) => unknown; // URL launcher
  authTimeout?: number; // Timeout ms (default: 300000)

  // UI
  successHtml?: string; // Success page HTML
  errorHtml?: string; // Error page template

  // Debugging
  onRequest?: (req: Request) => void; // Request logger
}

Usage Example

typescript
import type { BrowserAuthOptions } from "oauth-callback/mcp";
import { browserAuth, fileStore } from "oauth-callback/mcp";

const options: BrowserAuthOptions = {
  // Dynamic Client Registration - no credentials needed
  scope: "read write",

  // Custom server configuration
  port: 8080,
  hostname: "127.0.0.1",

  // Persistent storage
  store: fileStore("~/.myapp/tokens.json"),
  storeKey: "production",

  // Timeout
  authTimeout: 600000, // 10 minutes

  // Custom UI
  successHtml: "<h1>Success!</h1>",

  // Debugging
  onRequest: (req) => {
    console.log(`[OAuth] ${new URL(req.url).pathname}`);
  },
};

const authProvider = browserAuth(options);

Error Types

OAuthError

OAuth-specific error class.

typescript
class OAuthError extends Error {
  name: "OAuthError";
  error: string; // OAuth error code
  error_description?: string; // Human-readable description
  error_uri?: string; // Info URI

  constructor(error: string, description?: string, uri?: string);
}

TimeoutError

Timeout-specific error class.

typescript
class TimeoutError extends Error {
  name: "TimeoutError";
  constructor(message?: string);
}

Error Handling Example

typescript
import { OAuthError, TimeoutError } from "oauth-callback";
import type { CallbackResult } from "oauth-callback";

function handleAuthResult(result: CallbackResult) {
  // Check for OAuth errors in result
  if (result.error) {
    throw new OAuthError(
      result.error,
      result.error_description,
      result.error_uri,
    );
  }

  if (!result.code) {
    throw new Error("No authorization code received");
  }

  return result.code;
}

// Usage with proper error handling
try {
  const code = await getAuthCode(authUrl);
} catch (error) {
  if (error instanceof OAuthError) {
    console.error(`OAuth error: ${error.error}`);
  } else if (error instanceof TimeoutError) {
    console.error("Authorization timed out");
  } else {
    console.error("Unexpected error:", error);
  }
}

Type Guards

Useful type guard functions for runtime type checking:

typescript
import type { Tokens, ClientInfo } from "oauth-callback/mcp";

// Check if object is Tokens
function isTokens(obj: unknown): obj is Tokens {
  return (
    typeof obj === "object" &&
    obj !== null &&
    "accessToken" in obj &&
    typeof (obj as any).accessToken === "string"
  );
}

// Check if object is ClientInfo
function isClientInfo(obj: unknown): obj is ClientInfo {
  return (
    typeof obj === "object" &&
    obj !== null &&
    "clientId" in obj &&
    typeof (obj as any).clientId === "string"
  );
}

// Check if error is OAuthError
function isOAuthError(error: unknown): error is OAuthError {
  return error instanceof OAuthError;
}

// Usage
const stored = await store.get("key");
if (stored && isTokens(stored)) {
  console.log("Valid tokens:", stored.accessToken);
}

Generic Type Patterns

Result Type Pattern

typescript
type Result<T, E = Error> =
  | { success: true; data: T }
  | { success: false; error: E };

async function safeGetAuthCode(
  url: string,
): Promise<Result<CallbackResult, OAuthError | Error>> {
  try {
    const result = await getAuthCode(url);
    return { success: true, data: result };
  } catch (error) {
    if (error instanceof OAuthError) {
      return { success: false, error };
    }
    return { success: false, error: error as Error };
  }
}

// Usage
const result = await safeGetAuthCode(authUrl);
if (result.success) {
  console.log("Code:", result.data.code);
} else {
  console.error("Error:", result.error.message);
}

Storage Adapter Pattern

typescript
type StorageAdapter<T> = {
  load(): Promise<T | null>;
  save(data: T): Promise<void>;
  remove(): Promise<void>;
};

function createStorageAdapter<T>(
  store: TokenStore,
  key: string,
): StorageAdapter<T> {
  return {
    async load() {
      const data = await store.get(key);
      return data as T | null;
    },
    async save(data: T) {
      await store.set(key, data as any);
    },
    async remove() {
      await store.delete(key);
    },
  };
}

Type Exports

Main Package Exports

typescript
// From "oauth-callback"
export type {
  GetAuthCodeOptions,
  CallbackResult,
  CallbackServer,
  ServerOptions,
};

export { getAuthCode, OAuthError, inMemoryStore, fileStore };

MCP Sub-Package Exports

typescript
// From "oauth-callback/mcp"
export type { BrowserAuthOptions, TokenStore, OAuthStore, Tokens, ClientInfo };

export { browserAuth, inMemoryStore, fileStore };

Namespace Export

typescript
// Also available via namespace
import { mcp } from "oauth-callback";

// All MCP types and functions under mcp namespace
const authProvider = mcp.browserAuth({
  store: mcp.fileStore(),
});

TypeScript Configuration

For optimal type support, use these TypeScript settings:

json
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "types": ["node", "bun-types"]
  }
}

Type Versioning

The library follows semantic versioning for types:

  • Major version: Breaking type changes
  • Minor version: New types or optional properties
  • Patch version: Type fixes that don't break compatibility