All files / src/oauth/endpoints metadata.ts

100% Statements 13/13
83.33% Branches 5/6
100% Functions 3/3
100% Lines 13/13

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99                    22x                   22x   14x 14x     14x 14x   14x                           22x 9x     9x                                                                 9x                     22x 2x            
/**
 * OAuth Metadata Endpoint
 *
 * Implements the OAuth 2.0 Authorization Server Metadata endpoint
 * (RFC 8414) at /.well-known/oauth-authorization-server
 *
 * This endpoint allows OAuth clients to discover server capabilities.
 */
 
import { Request, Response } from "express";
import { HOST, PORT } from "../../config";
 
/**
 * Get the base URL from the request
 *
 * Handles reverse proxy scenarios by checking X-Forwarded-* headers.
 *
 * @param req - Express request
 * @returns Base URL string (e.g., "https://example.com")
 */
export function getBaseUrl(req: Request): string {
  // Check for forwarded protocol (from reverse proxy)
  const forwardedProto = req.get("x-forwarded-proto");
  const protocol = forwardedProto ?? req.protocol ?? "http";
 
  // Check for forwarded host (from reverse proxy)
  const forwardedHost = req.get("x-forwarded-host");
  const host = forwardedHost ?? req.get("host") ?? `${HOST}:${PORT}`;
 
  return `${protocol}://${host}`;
}
 
/**
 * OAuth Authorization Server Metadata endpoint handler
 *
 * Returns metadata about the OAuth server's capabilities including:
 * - Issuer
 * - Authorization and token endpoints
 * - Supported response types, grant types, and PKCE methods
 *
 * @param req - Express request
 * @param res - Express response
 */
export function metadataHandler(req: Request, res: Response): void {
  const baseUrl = getBaseUrl(req);
 
  // OAuth 2.0 Authorization Server Metadata (RFC 8414)
  const metadata = {
    // REQUIRED: Issuer identifier (must be HTTPS in production)
    issuer: baseUrl,
 
    // REQUIRED: Authorization endpoint
    authorization_endpoint: `${baseUrl}/authorize`,
 
    // REQUIRED: Token endpoint
    token_endpoint: `${baseUrl}/token`,
 
    // OPTIONAL: Supported response types
    response_types_supported: ["code"],
 
    // OPTIONAL: Supported grant types
    grant_types_supported: ["authorization_code", "refresh_token"],
 
    // OPTIONAL: Supported PKCE code challenge methods (S256 required for OAuth 2.1)
    code_challenge_methods_supported: ["S256"],
 
    // OPTIONAL: Token endpoint authentication methods
    // "none" for public clients (device flow with non-confidential apps)
    token_endpoint_auth_methods_supported: ["none"],
 
    // OPTIONAL: Supported scopes
    scopes_supported: ["mcp:tools", "mcp:resources"],
 
    // OPTIONAL: Registration endpoint (not implemented)
    // registration_endpoint: `${baseUrl}/register`,
 
    // MCP-specific metadata
    mcp_version: "2025-03-26",
  };
 
  res.json(metadata);
}
 
/**
 * Health check endpoint handler
 *
 * Returns server health status for monitoring.
 *
 * @param req - Express request
 * @param res - Express response
 */
export function healthHandler(req: Request, res: Response): void {
  res.json({
    status: "ok",
    mode: "oauth",
    timestamp: new Date().toISOString(),
  });
}