@enterprisestandard/esv 0.0.5-beta.20260115.2 → 0.0.5-beta.20260115.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/dist/iam/index.d.ts +8 -5
  2. package/dist/iam/index.js +5755 -664
  3. package/dist/iam/index.js.map +1 -1
  4. package/dist/index.d.ts +90 -10
  5. package/dist/index.js +6897 -152
  6. package/dist/index.js.map +1 -1
  7. package/dist/runner.d.ts +0 -36
  8. package/dist/runner.js +11407 -283
  9. package/dist/runner.js.map +1 -1
  10. package/dist/server/index.d.ts +88 -14
  11. package/dist/server/index.js +1387 -33
  12. package/dist/server/index.js.map +1 -1
  13. package/dist/sso/index.d.ts +8 -5
  14. package/dist/sso/index.js +365 -357
  15. package/dist/sso/index.js.map +1 -1
  16. package/dist/{types.d.ts → types-Bn1pr_xY.d.ts} +13 -11
  17. package/dist/workload/index.d.ts +8 -5
  18. package/dist/workload/index.js +393 -403
  19. package/dist/workload/index.js.map +1 -1
  20. package/package.json +2 -4
  21. package/dist/iam/index.d.ts.map +0 -1
  22. package/dist/index.d.ts.map +0 -1
  23. package/dist/runner.d.ts.map +0 -1
  24. package/dist/server/crypto.d.ts +0 -46
  25. package/dist/server/crypto.d.ts.map +0 -1
  26. package/dist/server/crypto.js +0 -134
  27. package/dist/server/crypto.js.map +0 -1
  28. package/dist/server/iam.d.ts +0 -11
  29. package/dist/server/iam.d.ts.map +0 -1
  30. package/dist/server/iam.js +0 -402
  31. package/dist/server/iam.js.map +0 -1
  32. package/dist/server/index.d.ts.map +0 -1
  33. package/dist/server/server.d.ts +0 -66
  34. package/dist/server/server.d.ts.map +0 -1
  35. package/dist/server/server.js +0 -223
  36. package/dist/server/server.js.map +0 -1
  37. package/dist/server/sso.d.ts +0 -11
  38. package/dist/server/sso.d.ts.map +0 -1
  39. package/dist/server/sso.js +0 -428
  40. package/dist/server/sso.js.map +0 -1
  41. package/dist/server/state.d.ts +0 -137
  42. package/dist/server/state.d.ts.map +0 -1
  43. package/dist/server/state.js +0 -152
  44. package/dist/server/state.js.map +0 -1
  45. package/dist/server/vault.d.ts +0 -11
  46. package/dist/server/vault.d.ts.map +0 -1
  47. package/dist/server/vault.js +0 -92
  48. package/dist/server/vault.js.map +0 -1
  49. package/dist/server/workload.d.ts +0 -19
  50. package/dist/server/workload.d.ts.map +0 -1
  51. package/dist/server/workload.js +0 -226
  52. package/dist/server/workload.js.map +0 -1
  53. package/dist/sso/index.d.ts.map +0 -1
  54. package/dist/tenant/index.d.ts +0 -17
  55. package/dist/tenant/index.d.ts.map +0 -1
  56. package/dist/tenant/index.js +0 -300
  57. package/dist/tenant/index.js.map +0 -1
  58. package/dist/types.d.ts.map +0 -1
  59. package/dist/types.js +0 -2
  60. package/dist/types.js.map +0 -1
  61. package/dist/utils.d.ts +0 -75
  62. package/dist/utils.d.ts.map +0 -1
  63. package/dist/utils.js +0 -139
  64. package/dist/utils.js.map +0 -1
  65. package/dist/workload/index.d.ts.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,oDAAoD;AACpD,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACpE,wBAAwB;AACxB,OAAO,EAAE,YAAY,EAAE,eAAe,EAAsB,WAAW,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzG,2CAA2C;AAC3C,OAAO,EAAE,UAAU,EAAE,WAAW,EAAiB,MAAM,YAAY,CAAC"}
1
+ {"version":3,"sources":["../../src/server/crypto.ts","../../src/server/server.ts","../../src/server/state.ts","../../src/server/iam.ts","../../src/server/sso.ts","../../src/server/vault.ts","../../src/server/workload.ts"],"sourcesContent":["/**\n * Cryptographic utilities for the ESV mock server\n *\n * Generates ephemeral RSA keys on startup for signing JWTs.\n * Uses only Node.js built-in crypto module.\n */\n\nimport * as crypto from 'node:crypto';\n\n// Key pair generated on module load\nlet privateKey: crypto.KeyObject;\nlet publicKey: crypto.KeyObject;\nlet keyId: string;\n\n/**\n * Initialize the cryptographic keys\n * Called on server startup\n */\nexport function initializeKeys(): void {\n const { publicKey: pubKey, privateKey: privKey } = crypto.generateKeyPairSync('rsa', {\n modulusLength: 2048,\n });\n\n privateKey = privKey;\n publicKey = pubKey;\n keyId = crypto.randomBytes(8).toString('hex');\n}\n\n/**\n * Get the key ID\n */\nexport function getKeyId(): string {\n return keyId;\n}\n\n/**\n * Base64URL encode a buffer or string\n */\nfunction base64UrlEncode(data: Buffer | string): string {\n const buffer = typeof data === 'string' ? Buffer.from(data) : data;\n return buffer.toString('base64url');\n}\n\n/**\n * Base64URL decode a string\n */\nfunction base64UrlDecode(data: string): Buffer {\n return Buffer.from(data, 'base64url');\n}\n\n/**\n * Sign a JWT with the private key\n */\nexport function signJwt(payload: Record<string, unknown>, expiresInSeconds: number = 3600): string {\n const now = Math.floor(Date.now() / 1000);\n\n const header = {\n alg: 'RS256',\n typ: 'JWT',\n kid: keyId,\n };\n\n const claims = {\n ...payload,\n iat: now,\n exp: now + expiresInSeconds,\n };\n\n const encodedHeader = base64UrlEncode(JSON.stringify(header));\n const encodedPayload = base64UrlEncode(JSON.stringify(claims));\n const signatureInput = `${encodedHeader}.${encodedPayload}`;\n\n const sign = crypto.createSign('RSA-SHA256');\n sign.update(signatureInput);\n const signature = sign.sign(privateKey);\n\n return `${signatureInput}.${base64UrlEncode(signature)}`;\n}\n\n/**\n * Verify a JWT signature\n */\nexport function verifyJwt(token: string): { valid: boolean; payload?: Record<string, unknown>; error?: string } {\n try {\n const parts = token.split('.');\n if (parts.length !== 3) {\n return { valid: false, error: 'Invalid JWT format' };\n }\n\n const [encodedHeader, encodedPayload, encodedSignature] = parts;\n const signatureInput = `${encodedHeader}.${encodedPayload}`;\n const signature = base64UrlDecode(encodedSignature);\n\n const verify = crypto.createVerify('RSA-SHA256');\n verify.update(signatureInput);\n const isValid = verify.verify(publicKey, signature);\n\n if (!isValid) {\n return { valid: false, error: 'Invalid signature' };\n }\n\n const payload = JSON.parse(base64UrlDecode(encodedPayload).toString('utf-8'));\n\n // Check expiration\n const now = Math.floor(Date.now() / 1000);\n if (payload.exp && payload.exp < now) {\n return { valid: false, error: 'Token expired' };\n }\n\n return { valid: true, payload };\n } catch (error) {\n return { valid: false, error: error instanceof Error ? error.message : 'Unknown error' };\n }\n}\n\n/**\n * Get the JWKS (JSON Web Key Set) for the public key\n */\nexport function getJwks(): { keys: Array<Record<string, string>> } {\n const jwk = publicKey.export({ format: 'jwk' });\n\n return {\n keys: [\n {\n kty: jwk.kty as string,\n n: jwk.n as string,\n e: jwk.e as string,\n kid: keyId,\n use: 'sig',\n alg: 'RS256',\n },\n ],\n };\n}\n\n/**\n * Generate a random string for codes, states, etc.\n */\nexport function generateRandomString(length: number = 32): string {\n return crypto.randomBytes(length).toString('hex').substring(0, length);\n}\n\n/**\n * Generate a UUID\n */\nexport function generateUUID(): string {\n return crypto.randomUUID();\n}\n\n/**\n * Verify PKCE code challenge\n */\nexport function verifyCodeChallenge(codeVerifier: string, codeChallenge: string): boolean {\n const hash = crypto.createHash('sha256').update(codeVerifier).digest();\n const computed = base64UrlEncode(hash);\n return computed === codeChallenge;\n}\n","/**\n * ESV Mock Server\n *\n * A zero-dependency mock server that simulates Vault, SSO/IDP, IAM/SCIM,\n * and Workload Identity services for testing Enterprise Standard integrations.\n *\n * @example\n * ```typescript\n * import { startServer, stopServer } from '@enterprisestandard/esv/server';\n *\n * // Start before tests\n * await startServer();\n *\n * // Initialize with ES_VAULT_URL, ES_VAULT_TOKEN, and ES_VAULT_PATH set\n * const es = await enterpriseStandard(undefined, {\n * vaultUrl: process.env.ES_VAULT_URL,\n * vaultToken: process.env.ES_VAULT_TOKEN,\n * vaultPath: process.env.ES_VAULT_PATH,\n * });\n *\n * // Stop after tests\n * await stopServer();\n * ```\n */\n\nimport { createServer, type IncomingMessage, type Server, type ServerResponse } from 'node:http';\nimport { initializeKeys } from './crypto.js';\nimport { handleIamRequest } from './iam.js';\nimport { handleSsoRequest } from './sso.js';\nimport { resetState } from './state.js';\nimport { handleVaultRequest } from './vault.js';\nimport { handleWhoamiRequest, handleWorkloadRequest } from './workload.js';\n\n/**\n * Handle webhook requests for tenant status updates\n */\nasync function handleWebhook(req: IncomingMessage, res: ServerResponse): Promise<void> {\n if (req.method !== 'POST') {\n res.writeHead(405, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Method not allowed' }));\n return;\n }\n\n // Read request body\n let body = '';\n req.on('data', (chunk) => {\n body += chunk.toString();\n });\n\n req.on('end', () => {\n try {\n const payload = JSON.parse(body);\n // Just acknowledge the webhook - we don't need to do anything with it for testing\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ received: true, payload }));\n } catch (_error) {\n res.writeHead(400, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Invalid JSON' }));\n }\n });\n}\n\nconst DEFAULT_PORT = 3555;\nconst DEFAULT_HOST = 'localhost';\n\nlet server: Server | null = null;\nlet isStarted = false;\n\n/**\n * Server configuration options\n */\nexport interface ServerOptions {\n /**\n * Port to listen on\n * @default 3555\n */\n port?: number;\n\n /**\n * Host to bind to\n * @default 'localhost'\n */\n host?: string;\n\n /**\n * Enable verbose logging\n * @default false\n */\n verbose?: boolean;\n}\n\n/**\n * Request router\n */\nasync function handleRequest(req: IncomingMessage, res: ServerResponse, verbose: boolean): Promise<void> {\n const url = new URL(req.url || '/', `http://${req.headers.host}`);\n const pathname = url.pathname;\n\n if (verbose) {\n console.log(`[ESV Server] ${req.method} ${pathname}`);\n }\n\n // Add CORS headers for local development\n res.setHeader('Access-Control-Allow-Origin', '*');\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE, OPTIONS');\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-Vault-Token');\n\n // Handle preflight requests\n if (req.method === 'OPTIONS') {\n res.writeHead(204);\n res.end();\n return;\n }\n\n try {\n // Route to appropriate handler\n if (pathname.startsWith('/vault')) {\n handleVaultRequest(req, res, pathname);\n } else if (pathname.startsWith('/sso')) {\n await handleSsoRequest(req, res, pathname);\n } else if (pathname.startsWith('/iam')) {\n await handleIamRequest(req, res, pathname);\n } else if (pathname.startsWith('/workload')) {\n await handleWorkloadRequest(req, res, pathname);\n } else if (pathname === '/api/whoami') {\n // Mock whoami endpoint for testing workload authentication independently\n handleWhoamiRequest(req, res);\n } else if (pathname === '/webhook') {\n // Webhook endpoint for tenant status updates\n handleWebhook(req, res);\n } else if (pathname === '/health' || pathname === '/') {\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ status: 'ok', service: 'esv-mock-server' }));\n } else {\n res.writeHead(404, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Not found' }));\n }\n } catch (error) {\n console.error('[ESV Server] Error handling request:', error);\n res.writeHead(500, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Internal server error' }));\n }\n}\n\n/**\n * Start the ESV mock server\n *\n * @param options - Server configuration options\n * @returns Promise that resolves when the server is listening\n */\nexport function startServer(options: ServerOptions = {}): Promise<void> {\n const { port = DEFAULT_PORT, host = DEFAULT_HOST, verbose = false } = options;\n\n if (isStarted && server) {\n if (verbose) {\n console.log('[ESV Server] Server already running');\n }\n return Promise.resolve();\n }\n\n return new Promise((resolve, reject) => {\n try {\n // Initialize cryptographic keys\n initializeKeys();\n\n // Reset state for fresh start\n resetState();\n\n server = createServer((req, res) => {\n handleRequest(req, res, verbose).catch((error) => {\n console.error('[ESV Server] Unhandled error:', error);\n if (!res.headersSent) {\n res.writeHead(500, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Internal server error' }));\n }\n });\n });\n\n server.on('error', (error: NodeJS.ErrnoException) => {\n if (error.code === 'EADDRINUSE') {\n // Port already in use - maybe server is already running\n if (verbose) {\n console.log(`[ESV Server] Port ${port} already in use, assuming server is running`);\n }\n isStarted = true;\n resolve();\n } else {\n reject(error);\n }\n });\n\n server.listen(port, host, () => {\n isStarted = true;\n console.log(`[ESV Server] Running at http://${host}:${port}/`);\n console.log('[ESV Server] Endpoints:');\n console.log(` - Vault: http://${host}:${port}/vault/v1/secret/data/esv/config`);\n console.log(` - SSO: http://${host}:${port}/sso/*`);\n console.log(` - IAM: http://${host}:${port}/iam/*`);\n console.log(` - Workload: http://${host}:${port}/workload/*`);\n console.log(` - Whoami: http://${host}:${port}/api/whoami`);\n console.log(` - Webhook: http://${host}:${port}/webhook`);\n resolve();\n });\n } catch (error) {\n reject(error);\n }\n });\n}\n\n/**\n * Stop the ESV mock server\n *\n * @returns Promise that resolves when the server has stopped\n */\nexport function stopServer(): Promise<void> {\n return new Promise((resolve, reject) => {\n if (!server) {\n isStarted = false;\n resolve();\n return;\n }\n\n server.close((error) => {\n if (error) {\n // Ignore errors if server wasn't running\n if ((error as NodeJS.ErrnoException).code === 'ERR_SERVER_NOT_RUNNING') {\n server = null;\n isStarted = false;\n resolve();\n return;\n }\n reject(error);\n return;\n }\n\n server = null;\n isStarted = false;\n console.log('[ESV Server] Stopped');\n resolve();\n });\n });\n}\n\n/**\n * Check if the server is running\n */\nexport function isServerRunning(): boolean {\n return isStarted;\n}\n\n/**\n * Get the server URL\n */\nexport function getServerUrl(options: ServerOptions = {}): string {\n const { port = DEFAULT_PORT, host = DEFAULT_HOST } = options;\n return `http://${host}:${port}`;\n}\n","/**\n * In-memory state management for the ESV mock server\n *\n * All state resets when the server restarts.\n */\n\n/**\n * SCIM User structure\n */\nexport interface ScimUser {\n id: string;\n schemas: string[];\n userName: string;\n displayName?: string;\n name?: {\n givenName?: string;\n familyName?: string;\n formatted?: string;\n };\n emails?: Array<{\n value: string;\n type?: string;\n primary?: boolean;\n }>;\n active?: boolean;\n groups?: Array<{\n value: string;\n display?: string;\n $ref?: string;\n }>;\n meta?: {\n resourceType: string;\n created: string;\n lastModified: string;\n location?: string;\n };\n externalId?: string;\n 'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User'?: {\n employeeNumber?: string;\n department?: string;\n manager?: { value?: string; displayName?: string };\n };\n}\n\n/**\n * SCIM Group structure\n */\nexport interface ScimGroup {\n id: string;\n schemas: string[];\n displayName: string;\n externalId?: string;\n members?: Array<{\n value: string;\n display?: string;\n $ref?: string;\n }>;\n meta?: {\n resourceType: string;\n created: string;\n lastModified: string;\n location?: string;\n };\n}\n\n/**\n * Authorization code data\n */\nexport interface AuthCode {\n code: string;\n userId: string;\n clientId: string;\n redirectUri: string;\n scope: string;\n codeChallenge?: string;\n codeChallengeMethod?: string;\n state?: string;\n createdAt: Date;\n expiresAt: Date;\n}\n\n/**\n * Refresh token data\n */\nexport interface RefreshToken {\n token: string;\n userId: string;\n clientId: string;\n scope: string;\n sessionId: string;\n createdAt: Date;\n expiresAt: Date;\n}\n\n/**\n * Session data\n */\nexport interface Session {\n id: string;\n userId: string;\n createdAt: Date;\n lastActivityAt: Date;\n}\n\n/**\n * Test user for SSO\n */\nexport interface TestUser {\n id: string;\n userName: string;\n email: string;\n name: string;\n givenName: string;\n familyName: string;\n picture?: string;\n}\n\n// ========== State Stores ==========\n\n// IAM Users\nconst users = new Map<string, ScimUser>();\n\n// IAM Groups\nconst groups = new Map<string, ScimGroup>();\n\n// Authorization codes (short-lived)\nconst authCodes = new Map<string, AuthCode>();\n\n// Refresh tokens\nconst refreshTokens = new Map<string, RefreshToken>();\n\n// Sessions\nconst sessions = new Map<string, Session>();\n\n// Default test user for SSO\nlet defaultTestUser: TestUser = {\n id: 'test-user-001',\n userName: 'testuser@example.com',\n email: 'testuser@example.com',\n name: 'Test User',\n givenName: 'Test',\n familyName: 'User',\n};\n\n// ========== User Operations ==========\n\nexport function getUsers(): ScimUser[] {\n return Array.from(users.values());\n}\n\nexport function getUser(id: string): ScimUser | undefined {\n return users.get(id);\n}\n\nexport function createUser(user: ScimUser): ScimUser {\n const now = new Date().toISOString();\n user.meta = {\n resourceType: 'User',\n created: now,\n lastModified: now,\n location: `/Users/${user.id}`,\n };\n users.set(user.id, user);\n return user;\n}\n\nexport function updateUser(id: string, updates: Partial<ScimUser>): ScimUser | undefined {\n const user = users.get(id);\n if (!user) return undefined;\n\n const updated = { ...user, ...updates };\n if (updated.meta) {\n updated.meta.lastModified = new Date().toISOString();\n }\n users.set(id, updated);\n return updated;\n}\n\nexport function deleteUser(id: string): boolean {\n return users.delete(id);\n}\n\n// ========== Group Operations ==========\n\nexport function getGroups(): ScimGroup[] {\n return Array.from(groups.values());\n}\n\nexport function getGroup(id: string): ScimGroup | undefined {\n return groups.get(id);\n}\n\nexport function createGroup(group: ScimGroup): ScimGroup {\n const now = new Date().toISOString();\n group.meta = {\n resourceType: 'Group',\n created: now,\n lastModified: now,\n location: `/Groups/${group.id}`,\n };\n groups.set(group.id, group);\n return group;\n}\n\nexport function updateGroup(id: string, updates: Partial<ScimGroup>): ScimGroup | undefined {\n const group = groups.get(id);\n if (!group) return undefined;\n\n const updated = { ...group, ...updates };\n if (updated.meta) {\n updated.meta.lastModified = new Date().toISOString();\n }\n groups.set(id, updated);\n return updated;\n}\n\nexport function deleteGroup(id: string): boolean {\n return groups.delete(id);\n}\n\n// ========== Auth Code Operations ==========\n\nexport function storeAuthCode(authCode: AuthCode): void {\n authCodes.set(authCode.code, authCode);\n}\n\nexport function getAuthCode(code: string): AuthCode | undefined {\n return authCodes.get(code);\n}\n\nexport function deleteAuthCode(code: string): boolean {\n return authCodes.delete(code);\n}\n\n// ========== Refresh Token Operations ==========\n\nexport function storeRefreshToken(refreshToken: RefreshToken): void {\n refreshTokens.set(refreshToken.token, refreshToken);\n}\n\nexport function getRefreshToken(token: string): RefreshToken | undefined {\n return refreshTokens.get(token);\n}\n\nexport function deleteRefreshToken(token: string): boolean {\n return refreshTokens.delete(token);\n}\n\nexport function deleteRefreshTokensBySession(sessionId: string): void {\n for (const [token, data] of refreshTokens.entries()) {\n if (data.sessionId === sessionId) {\n refreshTokens.delete(token);\n }\n }\n}\n\n// ========== Session Operations ==========\n\nexport function createSession(session: Session): void {\n sessions.set(session.id, session);\n}\n\nexport function getSession(id: string): Session | undefined {\n return sessions.get(id);\n}\n\nexport function deleteSession(id: string): boolean {\n // Also delete associated refresh tokens\n deleteRefreshTokensBySession(id);\n return sessions.delete(id);\n}\n\n// ========== Test User Operations ==========\n\nexport function getTestUser(): TestUser {\n return defaultTestUser;\n}\n\nexport function setTestUser(user: TestUser): void {\n defaultTestUser = user;\n}\n\n// ========== Reset State ==========\n\nexport function resetState(): void {\n users.clear();\n groups.clear();\n authCodes.clear();\n refreshTokens.clear();\n sessions.clear();\n defaultTestUser = {\n id: 'test-user-001',\n userName: 'testuser@example.com',\n email: 'testuser@example.com',\n name: 'Test User',\n givenName: 'Test',\n familyName: 'User',\n };\n}\n","/**\n * IAM/SCIM endpoint handlers for the ESV mock server\n *\n * Implements SCIM 2.0 endpoints for user and group management.\n */\n\nimport type { IncomingMessage, ServerResponse } from 'node:http';\nimport { generateUUID } from './crypto.js';\nimport {\n createGroup,\n createUser,\n deleteGroup,\n deleteUser,\n getGroup,\n getGroups,\n getUser,\n getUsers,\n type ScimGroup,\n type ScimUser,\n updateGroup,\n updateUser,\n} from './state.js';\n\nconst SCIM_CONTENT_TYPE = 'application/scim+json';\n\n/**\n * Parse JSON request body\n */\nasync function parseJsonBody(req: IncomingMessage): Promise<unknown> {\n return new Promise((resolve, reject) => {\n let body = '';\n req.on('data', (chunk) => {\n body += chunk.toString();\n });\n req.on('end', () => {\n try {\n resolve(body ? JSON.parse(body) : {});\n } catch (error) {\n reject(error);\n }\n });\n req.on('error', reject);\n });\n}\n\n/**\n * Validate authorization header\n */\nfunction validateAuth(req: IncomingMessage, res: ServerResponse): boolean {\n const auth = req.headers.authorization;\n if (!auth || !auth.startsWith('Bearer ')) {\n res.writeHead(401, { 'Content-Type': SCIM_CONTENT_TYPE });\n res.end(\n JSON.stringify({\n schemas: ['urn:ietf:params:scim:api:messages:2.0:Error'],\n status: '401',\n detail: 'Authorization required',\n }),\n );\n return false;\n }\n // We accept any bearer token for testing\n return true;\n}\n\n/**\n * Send SCIM error response\n */\nfunction sendScimError(res: ServerResponse, status: number, detail: string, scimType?: string): void {\n res.writeHead(status, { 'Content-Type': SCIM_CONTENT_TYPE });\n res.end(\n JSON.stringify({\n schemas: ['urn:ietf:params:scim:api:messages:2.0:Error'],\n status: String(status),\n scimType,\n detail,\n }),\n );\n}\n\n/**\n * Send SCIM list response\n */\nfunction sendListResponse<T>(res: ServerResponse, resources: T[], totalResults?: number): void {\n res.writeHead(200, { 'Content-Type': SCIM_CONTENT_TYPE });\n res.end(\n JSON.stringify({\n schemas: ['urn:ietf:params:scim:api:messages:2.0:ListResponse'],\n totalResults: totalResults ?? resources.length,\n startIndex: 1,\n itemsPerPage: resources.length,\n Resources: resources,\n }),\n );\n}\n\n/**\n * Handle IAM/SCIM requests\n */\nexport async function handleIamRequest(req: IncomingMessage, res: ServerResponse, pathname: string): Promise<void> {\n // Remove /iam prefix\n const iamPath = pathname.replace(/^\\/iam/, '');\n\n // Validate auth for all requests\n if (!validateAuth(req, res)) {\n return;\n }\n\n // Parse path to determine resource and ID\n const usersMatch = iamPath.match(/^\\/Users(?:\\/([^/]+))?$/);\n const groupsMatch = iamPath.match(/^\\/Groups(?:\\/([^/]+))?$/);\n\n if (usersMatch) {\n const userId = usersMatch[1];\n await handleUsersRequest(req, res, userId);\n return;\n }\n\n if (groupsMatch) {\n const groupId = groupsMatch[1];\n await handleGroupsRequest(req, res, groupId);\n return;\n }\n\n sendScimError(res, 404, 'Resource not found');\n}\n\n/**\n * Handle /Users requests\n */\nasync function handleUsersRequest(req: IncomingMessage, res: ServerResponse, userId?: string): Promise<void> {\n if (userId) {\n // Operations on a specific user\n switch (req.method) {\n case 'GET':\n handleGetUser(res, userId);\n break;\n case 'PUT':\n await handleReplaceUser(req, res, userId);\n break;\n case 'PATCH':\n await handlePatchUser(req, res, userId);\n break;\n case 'DELETE':\n handleDeleteUser(res, userId);\n break;\n default:\n sendScimError(res, 405, 'Method not allowed');\n }\n } else {\n // Operations on users collection\n switch (req.method) {\n case 'GET':\n handleListUsers(res);\n break;\n case 'POST':\n await handleCreateUser(req, res);\n break;\n default:\n sendScimError(res, 405, 'Method not allowed');\n }\n }\n}\n\n/**\n * Handle /Groups requests\n */\nasync function handleGroupsRequest(req: IncomingMessage, res: ServerResponse, groupId?: string): Promise<void> {\n if (groupId) {\n // Operations on a specific group\n switch (req.method) {\n case 'GET':\n handleGetGroup(res, groupId);\n break;\n case 'PUT':\n await handleReplaceGroup(req, res, groupId);\n break;\n case 'PATCH':\n await handlePatchGroup(req, res, groupId);\n break;\n case 'DELETE':\n handleDeleteGroup(res, groupId);\n break;\n default:\n sendScimError(res, 405, 'Method not allowed');\n }\n } else {\n // Operations on groups collection\n switch (req.method) {\n case 'GET':\n handleListGroups(res);\n break;\n case 'POST':\n await handleCreateGroup(req, res);\n break;\n default:\n sendScimError(res, 405, 'Method not allowed');\n }\n }\n}\n\n// ========== User Handlers ==========\n\nfunction handleListUsers(res: ServerResponse): void {\n const users = getUsers();\n sendListResponse(res, users);\n}\n\nfunction handleGetUser(res: ServerResponse, id: string): void {\n const user = getUser(id);\n if (!user) {\n sendScimError(res, 404, `User ${id} not found`, 'invalidValue');\n return;\n }\n res.writeHead(200, { 'Content-Type': SCIM_CONTENT_TYPE });\n res.end(JSON.stringify(user));\n}\n\nasync function handleCreateUser(req: IncomingMessage, res: ServerResponse): Promise<void> {\n try {\n const body = (await parseJsonBody(req)) as Partial<ScimUser>;\n\n if (!body.userName) {\n sendScimError(res, 400, 'userName is required', 'invalidValue');\n return;\n }\n\n const user: ScimUser = {\n id: generateUUID(),\n schemas: body.schemas || [\n 'urn:ietf:params:scim:schemas:core:2.0:User',\n 'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User',\n ],\n userName: body.userName,\n displayName: body.displayName,\n name: body.name,\n emails: body.emails,\n active: body.active ?? true,\n externalId: body.externalId,\n groups: [],\n 'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User':\n body['urn:ietf:params:scim:schemas:extension:enterprise:2.0:User'],\n };\n\n const created = createUser(user);\n res.writeHead(201, { 'Content-Type': SCIM_CONTENT_TYPE });\n res.end(JSON.stringify(created));\n } catch (_error) {\n sendScimError(res, 400, 'Invalid request body');\n }\n}\n\nasync function handleReplaceUser(req: IncomingMessage, res: ServerResponse, id: string): Promise<void> {\n const existing = getUser(id);\n if (!existing) {\n sendScimError(res, 404, `User ${id} not found`, 'invalidValue');\n return;\n }\n\n try {\n const body = (await parseJsonBody(req)) as Partial<ScimUser>;\n const updated = updateUser(id, { ...body, id });\n if (updated) {\n res.writeHead(200, { 'Content-Type': SCIM_CONTENT_TYPE });\n res.end(JSON.stringify(updated));\n } else {\n sendScimError(res, 404, `User ${id} not found`);\n }\n } catch (_error) {\n sendScimError(res, 400, 'Invalid request body');\n }\n}\n\nasync function handlePatchUser(req: IncomingMessage, res: ServerResponse, id: string): Promise<void> {\n const existing = getUser(id);\n if (!existing) {\n sendScimError(res, 404, `User ${id} not found`, 'invalidValue');\n return;\n }\n\n try {\n const body = (await parseJsonBody(req)) as { Operations?: Array<{ op: string; path?: string; value?: unknown }> };\n const operations = body.Operations || [];\n\n const updated = { ...existing };\n for (const op of operations) {\n if (op.op === 'replace' && op.path && op.value !== undefined) {\n // Simple path handling for common cases\n if (op.path === 'displayName') {\n updated.displayName = op.value as string;\n } else if (op.path === 'active') {\n updated.active = op.value as boolean;\n } else if (op.path.startsWith('name.')) {\n const namePart = op.path.split('.')[1] as keyof NonNullable<ScimUser['name']>;\n updated.name = { ...updated.name, [namePart]: op.value as string };\n }\n } else if (op.op === 'add' && op.path && op.value !== undefined) {\n if (op.path === 'emails') {\n updated.emails = [...(updated.emails || []), ...((op.value as ScimUser['emails']) || [])];\n }\n } else if (op.op === 'remove' && op.path) {\n if (op.path === 'displayName') {\n updated.displayName = undefined;\n }\n }\n }\n\n const result = updateUser(id, updated);\n if (result) {\n res.writeHead(200, { 'Content-Type': SCIM_CONTENT_TYPE });\n res.end(JSON.stringify(result));\n } else {\n sendScimError(res, 404, `User ${id} not found`);\n }\n } catch (_error) {\n sendScimError(res, 400, 'Invalid request body');\n }\n}\n\nfunction handleDeleteUser(res: ServerResponse, id: string): void {\n const deleted = deleteUser(id);\n if (!deleted) {\n sendScimError(res, 404, `User ${id} not found`, 'invalidValue');\n return;\n }\n res.writeHead(204);\n res.end();\n}\n\n// ========== Group Handlers ==========\n\nfunction handleListGroups(res: ServerResponse): void {\n const groups = getGroups();\n sendListResponse(res, groups);\n}\n\nfunction handleGetGroup(res: ServerResponse, id: string): void {\n const group = getGroup(id);\n if (!group) {\n sendScimError(res, 404, `Group ${id} not found`, 'invalidValue');\n return;\n }\n res.writeHead(200, { 'Content-Type': SCIM_CONTENT_TYPE });\n res.end(JSON.stringify(group));\n}\n\nasync function handleCreateGroup(req: IncomingMessage, res: ServerResponse): Promise<void> {\n try {\n const body = (await parseJsonBody(req)) as Partial<ScimGroup>;\n\n if (!body.displayName) {\n sendScimError(res, 400, 'displayName is required', 'invalidValue');\n return;\n }\n\n const group: ScimGroup = {\n id: generateUUID(),\n schemas: body.schemas || ['urn:ietf:params:scim:schemas:core:2.0:Group'],\n displayName: body.displayName,\n externalId: body.externalId,\n members: body.members || [],\n };\n\n const created = createGroup(group);\n res.writeHead(201, { 'Content-Type': SCIM_CONTENT_TYPE });\n res.end(JSON.stringify(created));\n } catch (_error) {\n sendScimError(res, 400, 'Invalid request body');\n }\n}\n\nasync function handleReplaceGroup(req: IncomingMessage, res: ServerResponse, id: string): Promise<void> {\n const existing = getGroup(id);\n if (!existing) {\n sendScimError(res, 404, `Group ${id} not found`, 'invalidValue');\n return;\n }\n\n try {\n const body = (await parseJsonBody(req)) as Partial<ScimGroup>;\n const updated = updateGroup(id, { ...body, id });\n if (updated) {\n res.writeHead(200, { 'Content-Type': SCIM_CONTENT_TYPE });\n res.end(JSON.stringify(updated));\n } else {\n sendScimError(res, 404, `Group ${id} not found`);\n }\n } catch (_error) {\n sendScimError(res, 400, 'Invalid request body');\n }\n}\n\nasync function handlePatchGroup(req: IncomingMessage, res: ServerResponse, id: string): Promise<void> {\n const existing = getGroup(id);\n if (!existing) {\n sendScimError(res, 404, `Group ${id} not found`, 'invalidValue');\n return;\n }\n\n try {\n const body = (await parseJsonBody(req)) as { Operations?: Array<{ op: string; path?: string; value?: unknown }> };\n const operations = body.Operations || [];\n\n const updated = { ...existing };\n for (const op of operations) {\n if (op.op === 'replace' && op.path && op.value !== undefined) {\n if (op.path === 'displayName') {\n updated.displayName = op.value as string;\n }\n } else if (op.op === 'add' && op.path && op.value !== undefined) {\n if (op.path === 'members') {\n updated.members = [...(updated.members || []), ...((op.value as ScimGroup['members']) || [])];\n }\n } else if (op.op === 'remove' && op.path) {\n if (op.path.startsWith('members[')) {\n // Parse member filter like members[value eq \"user-id\"]\n const match = op.path.match(/members\\[value eq \"([^\"]+)\"\\]/);\n if (match) {\n updated.members = (updated.members || []).filter((m) => m.value !== match[1]);\n }\n }\n }\n }\n\n const result = updateGroup(id, updated);\n if (result) {\n res.writeHead(200, { 'Content-Type': SCIM_CONTENT_TYPE });\n res.end(JSON.stringify(result));\n } else {\n sendScimError(res, 404, `Group ${id} not found`);\n }\n } catch (_error) {\n sendScimError(res, 400, 'Invalid request body');\n }\n}\n\nfunction handleDeleteGroup(res: ServerResponse, id: string): void {\n const deleted = deleteGroup(id);\n if (!deleted) {\n sendScimError(res, 404, `Group ${id} not found`, 'invalidValue');\n return;\n }\n res.writeHead(204);\n res.end();\n}\n","/**\n * SSO/OIDC endpoint handlers for the ESV mock server\n *\n * Implements a minimal OIDC provider for testing SSO integrations.\n */\n\nimport type { IncomingMessage, ServerResponse } from 'node:http';\nimport { generateRandomString, generateUUID, getJwks, signJwt, verifyCodeChallenge } from './crypto.js';\nimport {\n type AuthCode,\n createSession,\n deleteAuthCode,\n deleteRefreshToken,\n deleteSession,\n getAuthCode,\n getRefreshToken,\n getTestUser,\n type RefreshToken,\n storeAuthCode,\n storeRefreshToken,\n} from './state.js';\n\nconst ISSUER = 'http://localhost:3555/sso';\nconst TOKEN_EXPIRY = 3600; // 1 hour\nconst REFRESH_EXPIRY = 86400; // 24 hours\nconst CODE_EXPIRY = 300; // 5 minutes\n\n/**\n * Parse request body as URL-encoded form data\n */\nasync function parseFormBody(req: IncomingMessage): Promise<URLSearchParams> {\n return new Promise((resolve, reject) => {\n let body = '';\n req.on('data', (chunk) => {\n body += chunk.toString();\n });\n req.on('end', () => {\n resolve(new URLSearchParams(body));\n });\n req.on('error', reject);\n });\n}\n\n/**\n * Handle SSO requests\n */\nexport async function handleSsoRequest(req: IncomingMessage, res: ServerResponse, pathname: string): Promise<void> {\n // Remove /sso prefix\n const ssoPath = pathname.replace(/^\\/sso/, '');\n\n // GET /sso/authorize - Authorization endpoint\n if (req.method === 'GET' && ssoPath === '/authorize') {\n await handleAuthorize(req, res);\n return;\n }\n\n // POST /sso/token - Token endpoint\n if (req.method === 'POST' && ssoPath === '/token') {\n await handleToken(req, res);\n return;\n }\n\n // GET /sso/certs - JWKS endpoint\n if (req.method === 'GET' && ssoPath === '/certs') {\n handleCerts(res);\n return;\n }\n\n // POST /sso/revoke - Token revocation\n if (req.method === 'POST' && ssoPath === '/revoke') {\n await handleRevoke(req, res);\n return;\n }\n\n // GET /sso/userinfo - User info endpoint\n if (req.method === 'GET' && ssoPath === '/userinfo') {\n handleUserInfo(req, res);\n return;\n }\n\n // GET /sso/logout - End session endpoint\n if (req.method === 'GET' && ssoPath === '/logout') {\n handleLogout(req, res);\n return;\n }\n\n // POST /sso/logout - Back-channel logout\n if (req.method === 'POST' && ssoPath === '/logout/backchannel') {\n await handleBackChannelLogout(req, res);\n return;\n }\n\n // GET /sso/.well-known/openid-configuration\n if (req.method === 'GET' && ssoPath === '/.well-known/openid-configuration') {\n handleOpenIDConfig(res);\n return;\n }\n\n res.writeHead(404, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'not_found' }));\n}\n\n/**\n * Authorization endpoint - issues authorization codes\n *\n * In a real implementation, this would show a login form.\n * For testing, we auto-authenticate with the test user.\n */\nasync function handleAuthorize(req: IncomingMessage, res: ServerResponse): Promise<void> {\n const url = new URL(req.url || '', `http://${req.headers.host}`);\n const params = url.searchParams;\n\n const clientId = params.get('client_id');\n const redirectUri = params.get('redirect_uri');\n const responseType = params.get('response_type');\n const scope = params.get('scope') || 'openid';\n const state = params.get('state');\n const codeChallenge = params.get('code_challenge');\n const codeChallengeMethod = params.get('code_challenge_method');\n\n // Validate required parameters\n if (!clientId || !redirectUri || !responseType) {\n res.writeHead(400, { 'Content-Type': 'application/json' });\n res.end(\n JSON.stringify({\n error: 'invalid_request',\n error_description: 'Missing required parameters',\n }),\n );\n return;\n }\n\n if (responseType !== 'code') {\n res.writeHead(400, { 'Content-Type': 'application/json' });\n res.end(\n JSON.stringify({\n error: 'unsupported_response_type',\n error_description: 'Only code response type is supported',\n }),\n );\n return;\n }\n\n // Generate authorization code\n const testUser = getTestUser();\n const code = generateRandomString(32);\n\n const authCode: AuthCode = {\n code,\n userId: testUser.id,\n clientId,\n redirectUri,\n scope,\n codeChallenge: codeChallenge || undefined,\n codeChallengeMethod: codeChallengeMethod || undefined,\n state: state || undefined,\n createdAt: new Date(),\n expiresAt: new Date(Date.now() + CODE_EXPIRY * 1000),\n };\n\n storeAuthCode(authCode);\n\n // Redirect back with code\n const redirectUrl = new URL(redirectUri);\n redirectUrl.searchParams.set('code', code);\n if (state) {\n redirectUrl.searchParams.set('state', state);\n }\n\n res.writeHead(302, { Location: redirectUrl.toString() });\n res.end();\n}\n\n/**\n * Token endpoint - exchanges codes for tokens or refreshes tokens\n */\nasync function handleToken(req: IncomingMessage, res: ServerResponse): Promise<void> {\n const body = await parseFormBody(req);\n const grantType = body.get('grant_type');\n\n if (grantType === 'authorization_code') {\n await handleAuthorizationCodeGrant(body, res);\n } else if (grantType === 'refresh_token') {\n await handleRefreshTokenGrant(body, res);\n } else {\n res.writeHead(400, { 'Content-Type': 'application/json' });\n res.end(\n JSON.stringify({\n error: 'unsupported_grant_type',\n error_description: 'Only authorization_code and refresh_token are supported',\n }),\n );\n }\n}\n\n/**\n * Handle authorization code exchange\n */\nasync function handleAuthorizationCodeGrant(body: URLSearchParams, res: ServerResponse): Promise<void> {\n const code = body.get('code');\n const redirectUri = body.get('redirect_uri');\n const codeVerifier = body.get('code_verifier');\n\n if (!code || !redirectUri) {\n res.writeHead(400, { 'Content-Type': 'application/json' });\n res.end(\n JSON.stringify({\n error: 'invalid_request',\n error_description: 'Missing code or redirect_uri',\n }),\n );\n return;\n }\n\n const authCode = getAuthCode(code);\n\n if (!authCode) {\n res.writeHead(400, { 'Content-Type': 'application/json' });\n res.end(\n JSON.stringify({\n error: 'invalid_grant',\n error_description: 'Invalid or expired authorization code',\n }),\n );\n return;\n }\n\n // Validate redirect URI\n if (authCode.redirectUri !== redirectUri) {\n res.writeHead(400, { 'Content-Type': 'application/json' });\n res.end(\n JSON.stringify({\n error: 'invalid_grant',\n error_description: 'Redirect URI mismatch',\n }),\n );\n return;\n }\n\n // Validate PKCE if present\n if (authCode.codeChallenge && authCode.codeChallengeMethod === 'S256') {\n if (!codeVerifier || !verifyCodeChallenge(codeVerifier, authCode.codeChallenge)) {\n res.writeHead(400, { 'Content-Type': 'application/json' });\n res.end(\n JSON.stringify({\n error: 'invalid_grant',\n error_description: 'Invalid code verifier',\n }),\n );\n return;\n }\n }\n\n // Delete used code\n deleteAuthCode(code);\n\n // Create session\n const sessionId = generateUUID();\n createSession({\n id: sessionId,\n userId: authCode.userId,\n createdAt: new Date(),\n lastActivityAt: new Date(),\n });\n\n // Generate tokens\n const testUser = getTestUser();\n const tokens = generateTokens(testUser, authCode.clientId, authCode.scope, sessionId);\n\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(tokens));\n}\n\n/**\n * Handle refresh token grant\n */\nasync function handleRefreshTokenGrant(body: URLSearchParams, res: ServerResponse): Promise<void> {\n const refreshToken = body.get('refresh_token');\n\n if (!refreshToken) {\n res.writeHead(400, { 'Content-Type': 'application/json' });\n res.end(\n JSON.stringify({\n error: 'invalid_request',\n error_description: 'Missing refresh_token',\n }),\n );\n return;\n }\n\n const tokenData = getRefreshToken(refreshToken);\n\n if (!tokenData || tokenData.expiresAt < new Date()) {\n res.writeHead(400, { 'Content-Type': 'application/json' });\n res.end(\n JSON.stringify({\n error: 'invalid_grant',\n error_description: 'Invalid or expired refresh token',\n }),\n );\n return;\n }\n\n // Delete old refresh token (rotation)\n deleteRefreshToken(refreshToken);\n\n // Generate new tokens\n const testUser = getTestUser();\n const tokens = generateTokens(testUser, tokenData.clientId, tokenData.scope, tokenData.sessionId);\n\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(tokens));\n}\n\n/**\n * Generate access token, ID token, and refresh token\n */\nfunction generateTokens(\n user: ReturnType<typeof getTestUser>,\n clientId: string,\n scope: string,\n sessionId: string,\n): Record<string, unknown> {\n const now = Math.floor(Date.now() / 1000);\n\n // ID Token claims\n const idTokenClaims = {\n iss: ISSUER,\n sub: user.id,\n aud: clientId,\n nonce: generateRandomString(16),\n sid: sessionId,\n auth_time: now,\n email: user.email,\n email_verified: true,\n name: user.name,\n given_name: user.givenName,\n family_name: user.familyName,\n preferred_username: user.userName,\n picture: user.picture,\n };\n\n // Access token claims\n const accessTokenClaims = {\n iss: ISSUER,\n sub: user.id,\n aud: clientId,\n scope,\n sid: sessionId,\n };\n\n const idToken = signJwt(idTokenClaims, TOKEN_EXPIRY);\n const accessToken = signJwt(accessTokenClaims, TOKEN_EXPIRY);\n const refreshTokenValue = generateRandomString(64);\n\n // Store refresh token\n const refreshToken: RefreshToken = {\n token: refreshTokenValue,\n userId: user.id,\n clientId,\n scope,\n sessionId,\n createdAt: new Date(),\n expiresAt: new Date(Date.now() + REFRESH_EXPIRY * 1000),\n };\n storeRefreshToken(refreshToken);\n\n return {\n access_token: accessToken,\n token_type: 'Bearer',\n expires_in: TOKEN_EXPIRY,\n refresh_token: refreshTokenValue,\n refresh_expires_in: REFRESH_EXPIRY,\n id_token: idToken,\n scope,\n session_state: sessionId,\n };\n}\n\n/**\n * JWKS endpoint\n */\nfunction handleCerts(res: ServerResponse): void {\n const jwks = getJwks();\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(jwks));\n}\n\n/**\n * Token revocation endpoint\n */\nasync function handleRevoke(req: IncomingMessage, res: ServerResponse): Promise<void> {\n const body = await parseFormBody(req);\n const token = body.get('token');\n const tokenTypeHint = body.get('token_type_hint');\n\n if (token) {\n if (tokenTypeHint === 'refresh_token' || !tokenTypeHint) {\n deleteRefreshToken(token);\n }\n // Access tokens are stateless, can't be revoked\n }\n\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ success: true }));\n}\n\n/**\n * User info endpoint\n */\nfunction handleUserInfo(req: IncomingMessage, res: ServerResponse): void {\n // Extract and validate token\n const authHeader = req.headers.authorization;\n if (!authHeader?.startsWith('Bearer ')) {\n res.writeHead(401, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'invalid_token' }));\n return;\n }\n\n // For simplicity, we don't validate the token here - just return test user\n const user = getTestUser();\n\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(\n JSON.stringify({\n sub: user.id,\n email: user.email,\n email_verified: true,\n name: user.name,\n given_name: user.givenName,\n family_name: user.familyName,\n preferred_username: user.userName,\n picture: user.picture,\n }),\n );\n}\n\n/**\n * End session / logout endpoint\n */\nfunction handleLogout(req: IncomingMessage, res: ServerResponse): void {\n const url = new URL(req.url || '', `http://${req.headers.host}`);\n const postLogoutRedirectUri = url.searchParams.get('post_logout_redirect_uri');\n\n if (postLogoutRedirectUri) {\n res.writeHead(302, { Location: postLogoutRedirectUri });\n res.end();\n } else {\n res.writeHead(200, { 'Content-Type': 'text/html' });\n res.end('<html><body><h1>Logged out</h1></body></html>');\n }\n}\n\n/**\n * Back-channel logout endpoint\n */\nasync function handleBackChannelLogout(req: IncomingMessage, res: ServerResponse): Promise<void> {\n const body = await parseFormBody(req);\n const logoutToken = body.get('logout_token');\n\n if (!logoutToken) {\n res.writeHead(400, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'invalid_request', error_description: 'Missing logout_token' }));\n return;\n }\n\n // Parse the logout token to get sid\n try {\n const parts = logoutToken.split('.');\n if (parts.length >= 2) {\n const payload = JSON.parse(Buffer.from(parts[1], 'base64url').toString('utf-8'));\n if (payload.sid) {\n deleteSession(payload.sid);\n }\n }\n } catch {\n // Ignore parsing errors\n }\n\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ success: true }));\n}\n\n/**\n * OpenID Configuration endpoint\n */\nfunction handleOpenIDConfig(res: ServerResponse): void {\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(\n JSON.stringify({\n issuer: ISSUER,\n authorization_endpoint: `${ISSUER}/authorize`,\n token_endpoint: `${ISSUER}/token`,\n userinfo_endpoint: `${ISSUER}/userinfo`,\n jwks_uri: `${ISSUER}/certs`,\n end_session_endpoint: `${ISSUER}/logout`,\n revocation_endpoint: `${ISSUER}/revoke`,\n response_types_supported: ['code'],\n subject_types_supported: ['public'],\n id_token_signing_alg_values_supported: ['RS256'],\n scopes_supported: ['openid', 'profile', 'email'],\n token_endpoint_auth_methods_supported: ['client_secret_post', 'client_secret_basic'],\n claims_supported: [\n 'sub',\n 'iss',\n 'aud',\n 'exp',\n 'iat',\n 'nonce',\n 'email',\n 'email_verified',\n 'name',\n 'given_name',\n 'family_name',\n 'preferred_username',\n 'picture',\n 'sid',\n ],\n code_challenge_methods_supported: ['S256'],\n backchannel_logout_supported: true,\n backchannel_logout_session_supported: true,\n }),\n );\n}\n","/**\n * Vault endpoint handlers for the ESV mock server\n *\n * Provides configuration secrets for SSO, IAM, and Workload services.\n */\n\nimport type { IncomingMessage, ServerResponse } from 'node:http';\n\n/**\n * Default ESV configuration returned by the vault\n */\nfunction getEsvConfig(baseUrl: string = 'http://localhost:3555') {\n return {\n sso: {\n authority: `${baseUrl}/sso`,\n token_url: `${baseUrl}/sso/token`,\n authorization_url: `${baseUrl}/sso/authorize`,\n jwks_uri: `${baseUrl}/sso/certs`,\n client_id: 'local-test-client',\n client_secret: 'local-test-secret',\n redirect_uri: 'http://localhost:3000/api/auth/callback',\n scope: 'openid profile email',\n revocation_endpoint: `${baseUrl}/sso/revoke`,\n end_session_endpoint: `${baseUrl}/sso/logout`,\n },\n iam: {\n url: `${baseUrl}/iam`,\n // Note: The ESV server handles SCIM at /iam/Users and /iam/Groups\n // The url should point to the base IAM endpoint, not /scim/v2\n },\n workload: {\n token_url: `${baseUrl}/workload/token`,\n jwks_uri: `${baseUrl}/workload/certs`,\n client_id: 'local-workload-client',\n client_secret: 'local-workload-secret',\n issuer: `${baseUrl}/workload`,\n audience: `${baseUrl}/workload`,\n },\n };\n}\n\n/**\n * Handle vault requests\n */\nexport function handleVaultRequest(req: IncomingMessage, res: ServerResponse, pathname: string): void {\n // Remove /vault prefix\n const vaultPath = pathname.replace(/^\\/vault/, '');\n\n // Handle GET /vault/v1/secret/data/esv/config\n if (req.method === 'GET' && vaultPath === '/v1/secret/data/esv/config') {\n // Verify vault token\n const token = req.headers['x-vault-token'];\n if (token !== 'local-esv-token') {\n res.writeHead(403, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ errors: ['permission denied'] }));\n return;\n }\n\n const config = getEsvConfig();\n\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(\n JSON.stringify({\n request_id: 'local-esv-request',\n lease_id: '',\n renewable: false,\n lease_duration: 0,\n data: {\n data: config,\n metadata: {\n created_time: new Date().toISOString(),\n deletion_time: '',\n destroyed: false,\n version: 1,\n },\n },\n wrap_info: null,\n warnings: null,\n auth: null,\n }),\n );\n return;\n }\n\n // Handle GET /vault/v1/secret/data/* for other secrets\n if (req.method === 'GET' && vaultPath.startsWith('/v1/secret/data/')) {\n const token = req.headers['x-vault-token'];\n if (token !== 'local-esv-token') {\n res.writeHead(403, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ errors: ['permission denied'] }));\n return;\n }\n\n // Return empty secret for unknown paths\n res.writeHead(404, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ errors: ['secret not found'] }));\n return;\n }\n\n // 404 for unknown vault paths\n res.writeHead(404, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ errors: ['path not found'] }));\n}\n","/**\n * Workload Identity endpoint handlers for the ESV mock server\n *\n * Implements OAuth2 client credentials and JWT bearer grant for workload identity.\n */\n\nimport type { IncomingMessage, ServerResponse } from 'node:http';\nimport { getJwks, signJwt, verifyJwt } from './crypto.js';\n\nconst ISSUER = 'http://localhost:3555/workload';\nconst TOKEN_EXPIRY = 3600; // 1 hour\n\n// Valid client credentials for testing\nconst VALID_CLIENTS: Record<string, string> = {\n 'local-workload-client': 'local-workload-secret',\n};\n\n/**\n * Parse request body as URL-encoded form data\n */\nasync function parseFormBody(req: IncomingMessage): Promise<URLSearchParams> {\n return new Promise((resolve, reject) => {\n let body = '';\n req.on('data', (chunk) => {\n body += chunk.toString();\n });\n req.on('end', () => {\n resolve(new URLSearchParams(body));\n });\n req.on('error', reject);\n });\n}\n\n/**\n * Handle workload requests\n */\nexport async function handleWorkloadRequest(\n req: IncomingMessage,\n res: ServerResponse,\n pathname: string,\n): Promise<void> {\n // Remove /workload prefix\n const workloadPath = pathname.replace(/^\\/workload/, '');\n\n // POST /workload/token - Token endpoint\n if (req.method === 'POST' && workloadPath === '/token') {\n await handleToken(req, res);\n return;\n }\n\n // GET /workload/certs - JWKS endpoint\n if (req.method === 'GET' && workloadPath === '/certs') {\n handleCerts(res);\n return;\n }\n\n // POST /workload/validate - Token validation endpoint (for testing)\n if (req.method === 'POST' && workloadPath === '/validate') {\n handleValidate(req, res);\n return;\n }\n\n res.writeHead(404, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'not_found' }));\n}\n\n/**\n * Token endpoint - issues access tokens for client credentials or JWT bearer\n */\nasync function handleToken(req: IncomingMessage, res: ServerResponse): Promise<void> {\n const body = await parseFormBody(req);\n const grantType = body.get('grant_type');\n\n if (grantType === 'client_credentials') {\n handleClientCredentials(body, res);\n } else if (grantType === 'urn:ietf:params:oauth:grant-type:jwt-bearer') {\n handleJwtBearer(body, res);\n } else {\n res.writeHead(400, { 'Content-Type': 'application/json' });\n res.end(\n JSON.stringify({\n error: 'unsupported_grant_type',\n error_description: 'Only client_credentials and jwt-bearer are supported',\n }),\n );\n }\n}\n\n/**\n * Handle client credentials grant\n */\nfunction handleClientCredentials(body: URLSearchParams, res: ServerResponse): void {\n const clientId = body.get('client_id');\n const clientSecret = body.get('client_secret');\n const scope = body.get('scope') || '';\n\n if (!clientId || !clientSecret) {\n res.writeHead(400, { 'Content-Type': 'application/json' });\n res.end(\n JSON.stringify({\n error: 'invalid_request',\n error_description: 'Missing client_id or client_secret',\n }),\n );\n return;\n }\n\n // Validate credentials\n const expectedSecret = VALID_CLIENTS[clientId];\n if (!expectedSecret || expectedSecret !== clientSecret) {\n res.writeHead(401, { 'Content-Type': 'application/json' });\n res.end(\n JSON.stringify({\n error: 'invalid_client',\n error_description: 'Invalid client credentials',\n }),\n );\n return;\n }\n\n // Generate access token\n const accessTokenClaims = {\n iss: ISSUER,\n sub: clientId,\n aud: ISSUER,\n client_id: clientId,\n scope,\n };\n\n const accessToken = signJwt(accessTokenClaims, TOKEN_EXPIRY);\n\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(\n JSON.stringify({\n access_token: accessToken,\n token_type: 'Bearer',\n expires_in: TOKEN_EXPIRY,\n scope,\n }),\n );\n}\n\n/**\n * Handle JWT bearer grant\n */\nfunction handleJwtBearer(body: URLSearchParams, res: ServerResponse): void {\n const assertion = body.get('assertion');\n const scope = body.get('scope') || '';\n\n if (!assertion) {\n res.writeHead(400, { 'Content-Type': 'application/json' });\n res.end(\n JSON.stringify({\n error: 'invalid_request',\n error_description: 'Missing assertion',\n }),\n );\n return;\n }\n\n // Verify the JWT assertion\n const result = verifyJwt(assertion);\n\n if (!result.valid) {\n res.writeHead(400, { 'Content-Type': 'application/json' });\n res.end(\n JSON.stringify({\n error: 'invalid_grant',\n error_description: result.error || 'Invalid JWT assertion',\n }),\n );\n return;\n }\n\n // Extract workload ID from assertion\n const workloadId = result.payload?.sub as string;\n\n // Generate access token\n const accessTokenClaims = {\n iss: ISSUER,\n sub: workloadId,\n aud: ISSUER,\n workload_id: workloadId,\n scope: scope || (result.payload?.scope as string) || '',\n };\n\n const accessToken = signJwt(accessTokenClaims, TOKEN_EXPIRY);\n\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(\n JSON.stringify({\n access_token: accessToken,\n token_type: 'Bearer',\n expires_in: TOKEN_EXPIRY,\n scope: accessTokenClaims.scope,\n }),\n );\n}\n\n/**\n * JWKS endpoint\n */\nfunction handleCerts(res: ServerResponse): void {\n const jwks = getJwks();\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(jwks));\n}\n\n/**\n * Token validation endpoint (for testing)\n */\nfunction handleValidate(req: IncomingMessage, res: ServerResponse): void {\n const authHeader = req.headers.authorization;\n\n if (!authHeader || !authHeader.startsWith('Bearer ')) {\n res.writeHead(401, { 'Content-Type': 'application/json' });\n res.end(\n JSON.stringify({\n valid: false,\n error: 'Missing Authorization header',\n }),\n );\n return;\n }\n\n const token = authHeader.substring(7);\n const result = verifyJwt(token);\n\n if (!result.valid) {\n res.writeHead(401, { 'Content-Type': 'application/json' });\n res.end(\n JSON.stringify({\n valid: false,\n error: result.error,\n }),\n );\n return;\n }\n\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(\n JSON.stringify({\n valid: true,\n claims: result.payload,\n expiresAt: result.payload?.exp ? new Date((result.payload.exp as number) * 1000).toISOString() : undefined,\n }),\n );\n}\n\n/**\n * Mock /api/whoami endpoint for testing workload authentication\n *\n * This endpoint validates workload tokens and returns the workload identity,\n * allowing applications to be tested independently without requiring\n * another application to be running.\n */\nexport function handleWhoamiRequest(req: IncomingMessage, res: ServerResponse): void {\n const authHeader = req.headers.authorization;\n\n if (!authHeader || !authHeader.startsWith('Bearer ')) {\n res.writeHead(401, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Unauthorized' }));\n return;\n }\n\n const token = authHeader.substring(7);\n const result = verifyJwt(token);\n\n if (!result.valid) {\n res.writeHead(401, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Invalid token', details: result.error }));\n return;\n }\n\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(\n JSON.stringify({\n user: null,\n workload: {\n workload_id: result.payload?.sub,\n client_id: result.payload?.client_id,\n scope: result.payload?.scope,\n },\n }),\n );\n}\n"],"mappings":"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","names":["users","groups","ISSUER","TOKEN_EXPIRY","parseFormBody","handleToken","handleCerts"]}
@@ -1,18 +1,21 @@
1
+ import { S as SSOValidationConfig, T as TestDef, V as ValidationSuiteResult } from '../types-Bn1pr_xY.js';
2
+ import '@enterprisestandard/react';
3
+
1
4
  /**
2
5
  * SSO Validation Tests
3
6
  *
4
7
  * These tests validate that an application correctly implements
5
8
  * Enterprise Standard SSO (Single Sign-On) functionality.
6
9
  */
7
- import type { SSOValidationConfig, TestDef, ValidationSuiteResult } from '../types';
10
+
8
11
  /**
9
12
  * Runs all SSO validation tests
10
13
  */
11
- export declare function validateSSO(config: SSOValidationConfig): Promise<ValidationSuiteResult>;
14
+ declare function validateSSO(config: SSOValidationConfig): Promise<ValidationSuiteResult>;
12
15
  /**
13
16
  * Creates Vitest-compatible test suite for SSO validation
14
17
  */
15
- export declare function createSSOTests(config: SSOValidationConfig): {
18
+ declare function createSSOTests(config: SSOValidationConfig): {
16
19
  tests: TestDef[];
17
20
  ext: {
18
21
  createJITTests: () => Array<TestDef>;
@@ -20,5 +23,5 @@ export declare function createSSOTests(config: SSOValidationConfig): {
20
23
  createBackChannelLogoutTests: () => Array<TestDef>;
21
24
  };
22
25
  };
23
- export type { SSOValidationConfig };
24
- //# sourceMappingURL=index.d.ts.map
26
+
27
+ export { SSOValidationConfig, createSSOTests, validateSSO };