Skip to main content
Glama
nickytonline

Pimp My Ride MCP Server

by nickytonline
pomerium.ts5.03 kB
/** * Pomerium authentication resolver * Extracts user identity from Pomerium proxy headers */ import type { Request } from "express"; /** * User identity extracted from Pomerium headers */ export interface UserIdentity { /** Unique user identifier (from Pomerium subject or user ID) */ userId: string; /** User email (if available) */ email?: string; /** Display name (if available) */ name?: string; /** Whether the user is authenticated (vs anonymous) */ authenticated: boolean; } /** * Pomerium header names * See: https://www.pomerium.com/docs/reference/forward-auth */ const POMERIUM_HEADERS = { // User identifier (typically email or subject) USER_ID: "x-pomerium-claim-sub", // User email EMAIL: "x-pomerium-claim-email", // Display name NAME: "x-pomerium-claim-name", // JWT assertion JWT: "x-pomerium-jwt-assertion", } as const; /** * Extract user identity from Pomerium headers * @param req - Express request object * @returns User identity or anonymous identity if headers are missing */ export function resolveIdentity(req: Request): UserIdentity { // Try to get user ID from Pomerium headers const userId = req.headers[POMERIUM_HEADERS.USER_ID] as string | undefined; const email = req.headers[POMERIUM_HEADERS.EMAIL] as string | undefined; const name = req.headers[POMERIUM_HEADERS.NAME] as string | undefined; // If we have a user ID, return authenticated identity if (userId) { return { userId: sanitizeUserId(userId), email, name, authenticated: true, }; } // Log warning about anonymous access console.warn( "⚠️ Anonymous user detected - no Pomerium authentication headers found. In production, configure Pomerium proxy.", ); // Fallback: check for JWT assertion const jwt = req.headers[POMERIUM_HEADERS.JWT] as string | undefined; if (jwt) { try { // Parse JWT (base64 decode the payload without verification) const payload = parseJWTPayload(jwt); if (payload.sub) { return { userId: sanitizeUserId(payload.sub), email: payload.email, name: payload.name, authenticated: true, }; } } catch (error) { // JWT parsing failed, fall through to anonymous } } // Anonymous/dev mode: generate a session-based ID // In production, you might want to reject unauthenticated requests const anonymousId = generateAnonymousId(req); return { userId: anonymousId, authenticated: false, }; } /** * Sanitize user ID to ensure it's safe for use as a key * Removes potentially problematic characters and normalizes format */ function sanitizeUserId(userId: string): string { // Remove any null bytes, newlines, or other control characters let sanitized = userId.replace(/[\x00-\x1F\x7F]/g, ""); // Trim whitespace sanitized = sanitized.trim(); // Ensure it's not empty after sanitization if (!sanitized) { throw new Error("Invalid user ID: empty after sanitization"); } // Normalize to lowercase for consistency return sanitized.toLowerCase(); } /** * Parse JWT payload without verification * WARNING: This does NOT verify the JWT signature. Only use with trusted sources (Pomerium) * @param jwt - JWT token string * @returns Decoded payload */ function parseJWTPayload(jwt: string): { sub?: string; email?: string; name?: string; [key: string]: unknown; } { const parts = jwt.split("."); if (parts.length !== 3) { throw new Error("Invalid JWT format"); } const payload = parts[1]; const decoded = Buffer.from(payload, "base64").toString("utf-8"); return JSON.parse(decoded); } /** * Generate a deterministic anonymous ID based on request characteristics * This allows anonymous users to maintain a session across requests * In production, you might want to reject anonymous requests instead */ function generateAnonymousId(req: Request): string { // Use IP and User-Agent to generate a pseudo-stable anonymous ID const ip = req.ip || "unknown"; const userAgent = req.headers["user-agent"] || "unknown"; // Create a simple hash-like ID (not cryptographically secure, just for dev) const combined = `${ip}:${userAgent}`; const hash = Array.from(combined).reduce( (acc, char) => ((acc << 5) - acc + char.charCodeAt(0)) | 0, 0, ); return `anon_${Math.abs(hash).toString(36)}`; } /** * Middleware to require authentication * Throws an error if the user is not authenticated */ export function requireAuth(identity: UserIdentity): void { if (!identity.authenticated) { throw new Error( "Authentication required. Please configure Pomerium authentication.", ); } } /** * Check if a user is allowed to access a build * @param identity - User identity * @param buildUserId - User ID that owns the build * @returns True if access is allowed */ export function canAccessBuild( identity: UserIdentity, buildUserId: string, ): boolean { return identity.userId === buildUserId; }

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/nickytonline/pimp-my-ride-mcp'

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