Skip to main content
Glama
errors.ts5.78 kB
/** * db-mcp - OAuth Error Classes * * Module-prefixed error classes for OAuth 2.0 authentication * and authorization failures. */ import { DbMcpError } from '../types/index.js'; import { ERROR_CODES } from '../utils/logger.js'; // ============================================================================= // Base OAuth Error // ============================================================================= /** * Base class for OAuth-related errors */ export class OAuthError extends DbMcpError { /** HTTP status code for this error */ readonly httpStatus: number; /** WWW-Authenticate header value */ readonly wwwAuthenticate?: string | undefined; constructor( message: string, code: string, httpStatus: number, details?: Record<string, unknown>, wwwAuthenticate?: string ) { super(message, code, details); this.name = 'OAuthError'; this.httpStatus = httpStatus; this.wwwAuthenticate = wwwAuthenticate; } } // ============================================================================= // Authentication Errors (401) // ============================================================================= /** * Token is missing from the request */ export class TokenMissingError extends OAuthError { constructor(realm = 'db-mcp') { super( 'No access token provided', ERROR_CODES.AUTH.TOKEN_MISSING.full, 401, undefined, `Bearer realm="${realm}"` ); this.name = 'TokenMissingError'; } } /** * Token is invalid (malformed, wrong format, etc.) */ export class InvalidTokenError extends OAuthError { constructor(message = 'Invalid access token', details?: Record<string, unknown>) { super( message, ERROR_CODES.AUTH.TOKEN_INVALID.full, 401, details, 'Bearer error="invalid_token"' ); this.name = 'InvalidTokenError'; } } /** * Token has expired */ export class TokenExpiredError extends OAuthError { constructor(expiredAt?: Date) { super( 'Access token has expired', ERROR_CODES.AUTH.TOKEN_EXPIRED.full, 401, expiredAt ? { expiredAt: expiredAt.toISOString() } : undefined, 'Bearer error="invalid_token", error_description="Token has expired"' ); this.name = 'TokenExpiredError'; } } /** * Token signature is invalid */ export class InvalidSignatureError extends OAuthError { constructor(message = 'Token signature verification failed') { super( message, ERROR_CODES.AUTH.SIGNATURE_INVALID.full, 401, undefined, 'Bearer error="invalid_token", error_description="Signature verification failed"' ); this.name = 'InvalidSignatureError'; } } // ============================================================================= // Authorization Errors (403) // ============================================================================= /** * Token does not have required scope */ export class InsufficientScopeError extends OAuthError { constructor(requiredScope: string | string[], providedScopes?: string[]) { const required = Array.isArray(requiredScope) ? requiredScope : [requiredScope]; const scopeValue = required.join(' '); super( `Insufficient scope. Required: ${scopeValue}`, ERROR_CODES.AUTH.SCOPE_DENIED.full, 403, { requiredScope: required, providedScopes }, `Bearer error="insufficient_scope", scope="${scopeValue}"` ); this.name = 'InsufficientScopeError'; } } // ============================================================================= // Server Errors (500) // ============================================================================= /** * Failed to discover authorization server metadata */ export class AuthServerDiscoveryError extends OAuthError { constructor(serverUrl: string, cause?: Error) { super( `Failed to discover authorization server metadata: ${serverUrl}`, ERROR_CODES.AUTH.DISCOVERY_FAILED.full, 500, { serverUrl, cause: cause?.message } ); this.name = 'AuthServerDiscoveryError'; } } /** * Failed to fetch JWKS */ export class JwksFetchError extends OAuthError { constructor(jwksUri: string, cause?: Error) { super( `Failed to fetch JWKS: ${jwksUri}`, ERROR_CODES.AUTH.JWKS_FETCH_FAILED.full, 500, { jwksUri, cause: cause?.message } ); this.name = 'JwksFetchError'; } } /** * Failed to register client */ export class ClientRegistrationError extends OAuthError { constructor(message: string, details?: Record<string, unknown>) { super( message, ERROR_CODES.AUTH.REGISTRATION_FAILED.full, 500, details ); this.name = 'ClientRegistrationError'; } } // ============================================================================= // Utility Functions // ============================================================================= /** * Check if an error is an OAuth error */ export function isOAuthError(error: unknown): error is OAuthError { return error instanceof OAuthError; } /** * Get WWW-Authenticate header for an OAuth error */ export function getWWWAuthenticateHeader(error: OAuthError, realm = 'db-mcp'): string { return error.wwwAuthenticate ?? `Bearer realm="${realm}"`; }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/neverinfamous/db-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server