Skip to main content
Glama
authentication.test.ts19.5 kB
import { IncomingMessage } from "http"; import { describe, expect, it } from "vitest"; import { AuthenticationMiddleware } from "./authentication.js"; describe("AuthenticationMiddleware", () => { const createMockRequest = ( headers: Record<string, string> = {}, ): IncomingMessage => { // Simulate Node.js http module behavior which converts all header names to lowercase const lowercaseHeaders: Record<string, string> = {}; for (const [key, value] of Object.entries(headers)) { lowercaseHeaders[key.toLowerCase()] = value; } return { headers: lowercaseHeaders, } as IncomingMessage; }; describe("when no auth is configured", () => { it("should allow all requests", () => { const middleware = new AuthenticationMiddleware({}); const req = createMockRequest(); expect(middleware.validateRequest(req)).toBe(true); }); it("should allow requests even with headers", () => { const middleware = new AuthenticationMiddleware({}); const req = createMockRequest({ "x-api-key": "some-key" }); expect(middleware.validateRequest(req)).toBe(true); }); }); describe("X-API-Key validation", () => { const apiKey = "test-api-key-123"; it("should accept valid API key", () => { const middleware = new AuthenticationMiddleware({ apiKey }); const req = createMockRequest({ "x-api-key": apiKey }); expect(middleware.validateRequest(req)).toBe(true); }); it("should reject missing API key", () => { const middleware = new AuthenticationMiddleware({ apiKey }); const req = createMockRequest(); expect(middleware.validateRequest(req)).toBe(false); }); it("should reject incorrect API key", () => { const middleware = new AuthenticationMiddleware({ apiKey }); const req = createMockRequest({ "x-api-key": "wrong-key" }); expect(middleware.validateRequest(req)).toBe(false); }); it("should reject empty API key", () => { const middleware = new AuthenticationMiddleware({ apiKey }); const req = createMockRequest({ "x-api-key": "" }); expect(middleware.validateRequest(req)).toBe(false); }); it("should be case-insensitive for header names", () => { const middleware = new AuthenticationMiddleware({ apiKey }); const req = createMockRequest({ "X-API-KEY": apiKey }); expect(middleware.validateRequest(req)).toBe(true); }); it("should work with mixed case header names", () => { const middleware = new AuthenticationMiddleware({ apiKey }); const req = createMockRequest({ "X-Api-Key": apiKey }); expect(middleware.validateRequest(req)).toBe(true); }); it("should handle array headers (if multiple same headers)", () => { const middleware = new AuthenticationMiddleware({ apiKey }); const req = { headers: { "x-api-key": [apiKey, "another-key"], }, } as unknown as IncomingMessage; // Should fail because header is an array, not a string expect(middleware.validateRequest(req)).toBe(false); }); }); describe("getUnauthorizedResponse", () => { it("should return proper unauthorized response", () => { const middleware = new AuthenticationMiddleware({ apiKey: "test" }); const response = middleware.getUnauthorizedResponse(); expect(response.headers["Content-Type"]).toBe("application/json"); const body = JSON.parse(response.body); expect(body.error.code).toBe(401); expect(body.error.message).toBe( "Unauthorized: Invalid or missing API key", ); expect(body.jsonrpc).toBe("2.0"); expect(body.id).toBe(null); }); it("should have consistent body format regardless of configuration", () => { const middleware1 = new AuthenticationMiddleware({}); const middleware2 = new AuthenticationMiddleware({ apiKey: "test" }); const response1 = middleware1.getUnauthorizedResponse(); const response2 = middleware2.getUnauthorizedResponse(); expect(response1.body).toEqual(response2.body); }); it("should not include WWW-Authenticate header without OAuth config", () => { const middleware = new AuthenticationMiddleware({ apiKey: "test" }); const response = middleware.getUnauthorizedResponse(); expect(response.headers["WWW-Authenticate"]).toBeUndefined(); }); it("should include WWW-Authenticate header with OAuth config", () => { const middleware = new AuthenticationMiddleware({ apiKey: "test", oauth: { protectedResource: { resource: "https://example.com", }, }, }); const response = middleware.getUnauthorizedResponse(); expect(response.headers["WWW-Authenticate"]).toBe( 'Bearer resource_metadata="https://example.com/.well-known/oauth-protected-resource", error="invalid_token", error_description="Unauthorized: Invalid or missing API key"', ); }); it("should handle OAuth config with trailing slash in resource URL", () => { const middleware = new AuthenticationMiddleware({ apiKey: "test", oauth: { protectedResource: { resource: "https://example.com/", }, }, }); const response = middleware.getUnauthorizedResponse(); expect(response.headers["WWW-Authenticate"]).toBe( 'Bearer resource_metadata="https://example.com//.well-known/oauth-protected-resource", error="invalid_token", error_description="Unauthorized: Invalid or missing API key"', ); }); it("should include minimal WWW-Authenticate header when OAuth config is empty object", () => { const middleware = new AuthenticationMiddleware({ apiKey: "test", oauth: {}, }); const response = middleware.getUnauthorizedResponse(); // Even with empty oauth object, default error and error_description are added expect(response.headers["WWW-Authenticate"]).toBe( 'Bearer error="invalid_token", error_description="Unauthorized: Invalid or missing API key"', ); }); it("should include minimal WWW-Authenticate header when protectedResource is empty", () => { const middleware = new AuthenticationMiddleware({ apiKey: "test", oauth: { protectedResource: {}, }, }); const response = middleware.getUnauthorizedResponse(); // Even without resource_metadata, default error and error_description are added expect(response.headers["WWW-Authenticate"]).toBe( 'Bearer error="invalid_token", error_description="Unauthorized: Invalid or missing API key"', ); }); it("should include WWW-Authenticate header with OAuth config but no apiKey", () => { const middleware = new AuthenticationMiddleware({ oauth: { protectedResource: { resource: "https://example.com", }, }, }); const response = middleware.getUnauthorizedResponse(); expect(response.headers["WWW-Authenticate"]).toBe( 'Bearer resource_metadata="https://example.com/.well-known/oauth-protected-resource", error="invalid_token", error_description="Unauthorized: Invalid or missing API key"', ); }); it("should include realm in WWW-Authenticate header when configured", () => { const middleware = new AuthenticationMiddleware({ apiKey: "test", oauth: { protectedResource: { resource: "https://example.com", }, realm: "example-realm", }, }); const response = middleware.getUnauthorizedResponse(); expect(response.headers["WWW-Authenticate"]).toContain( 'realm="example-realm"', ); expect(response.headers["WWW-Authenticate"]).toContain( 'resource_metadata="https://example.com/.well-known/oauth-protected-resource"', ); }); it("should include custom error in WWW-Authenticate header via options", () => { const middleware = new AuthenticationMiddleware({ apiKey: "test", oauth: { protectedResource: { resource: "https://example.com", }, }, }); const response = middleware.getUnauthorizedResponse({ error: "insufficient_scope", error_description: "The request requires higher privileges", }); expect(response.headers["WWW-Authenticate"]).toContain( 'error="insufficient_scope"', ); expect(response.headers["WWW-Authenticate"]).toContain( 'error_description="The request requires higher privileges"', ); }); it("should include scope in WWW-Authenticate header", () => { const middleware = new AuthenticationMiddleware({ apiKey: "test", oauth: { protectedResource: { resource: "https://example.com", }, scope: "read write", }, }); const response = middleware.getUnauthorizedResponse(); expect(response.headers["WWW-Authenticate"]).toContain( 'scope="read write"', ); }); it("should override config error with options error", () => { const middleware = new AuthenticationMiddleware({ apiKey: "test", oauth: { error: "invalid_request", error_description: "Config error description", protectedResource: { resource: "https://example.com", }, }, }); const response = middleware.getUnauthorizedResponse({ error: "invalid_token", error_description: "Options error description", }); expect(response.headers["WWW-Authenticate"]).toContain( 'error="invalid_token"', ); expect(response.headers["WWW-Authenticate"]).toContain( 'error_description="Options error description"', ); expect(response.headers["WWW-Authenticate"]).not.toContain( "invalid_request", ); expect(response.headers["WWW-Authenticate"]).not.toContain( "Config error description", ); }); it("should include error_uri in WWW-Authenticate header", () => { const middleware = new AuthenticationMiddleware({ apiKey: "test", oauth: { error_uri: "https://example.com/errors/auth", protectedResource: { resource: "https://example.com", }, }, }); const response = middleware.getUnauthorizedResponse(); expect(response.headers["WWW-Authenticate"]).toContain( 'error_uri="https://example.com/errors/auth"', ); }); it("should properly escape quotes in error_description", () => { const middleware = new AuthenticationMiddleware({ apiKey: "test", oauth: { protectedResource: { resource: "https://example.com", }, }, }); const response = middleware.getUnauthorizedResponse({ error_description: 'Token "abc123" is invalid', }); expect(response.headers["WWW-Authenticate"]).toContain( 'error_description="Token \\"abc123\\" is invalid"', ); }); it("should include all parameters in correct order", () => { const middleware = new AuthenticationMiddleware({ apiKey: "test", oauth: { error: "invalid_token", error_description: "Token expired", error_uri: "https://example.com/errors", protectedResource: { resource: "https://example.com", }, realm: "my-realm", scope: "read write", }, }); const response = middleware.getUnauthorizedResponse(); const header = response.headers["WWW-Authenticate"]; expect(header).toContain('realm="my-realm"'); expect(header).toContain( 'resource_metadata="https://example.com/.well-known/oauth-protected-resource"', ); expect(header).toContain('error="invalid_token"'); expect(header).toContain('error_description="Token expired"'); expect(header).toContain('error_uri="https://example.com/errors"'); expect(header).toContain('scope="read write"'); // Check order: realm, resource_metadata, error, error_description, error_uri, scope expect(header.indexOf("realm=")).toBeLessThan( header.indexOf("resource_metadata="), ); expect(header.indexOf("resource_metadata=")).toBeLessThan( header.indexOf("error="), ); expect(header.indexOf("error=")).toBeLessThan( header.indexOf("error_description="), ); }); }); describe("getScopeChallengeResponse", () => { it("should return 403 status code", () => { const middleware = new AuthenticationMiddleware({ oauth: { protectedResource: { resource: "https://example.com", }, }, }); const response = middleware.getScopeChallengeResponse(["read", "write"]); expect(response.statusCode).toBe(403); }); it("should include required scopes in WWW-Authenticate header", () => { const middleware = new AuthenticationMiddleware({ oauth: { protectedResource: { resource: "https://example.com", }, }, }); const response = middleware.getScopeChallengeResponse(["read", "write"]); expect(response.headers["WWW-Authenticate"]).toContain( 'error="insufficient_scope"', ); expect(response.headers["WWW-Authenticate"]).toContain( 'scope="read write"', ); expect(response.headers["WWW-Authenticate"]).toContain( 'resource_metadata="https://example.com/.well-known/oauth-protected-resource"', ); }); it("should include error_description in WWW-Authenticate header", () => { const middleware = new AuthenticationMiddleware({ oauth: { protectedResource: { resource: "https://example.com", }, }, }); const response = middleware.getScopeChallengeResponse( ["admin"], "Admin access required", ); expect(response.headers["WWW-Authenticate"]).toContain( 'error_description="Admin access required"', ); }); it("should escape quotes in error_description", () => { const middleware = new AuthenticationMiddleware({ oauth: { protectedResource: { resource: "https://example.com", }, }, }); const response = middleware.getScopeChallengeResponse( ["admin"], 'Requires "admin" scope', ); expect(response.headers["WWW-Authenticate"]).toContain( 'error_description="Requires \\"admin\\" scope"', ); }); it("should include request ID in response body", () => { const middleware = new AuthenticationMiddleware({ oauth: { protectedResource: { resource: "https://example.com", }, }, }); const response = middleware.getScopeChallengeResponse( ["read"], undefined, 123, ); const body = JSON.parse(response.body); expect(body.id).toBe(123); }); it("should include required scopes in response body data", () => { const middleware = new AuthenticationMiddleware({ oauth: { protectedResource: { resource: "https://example.com", }, }, }); const response = middleware.getScopeChallengeResponse(["read", "write"]); const body = JSON.parse(response.body); expect(body.error.code).toBe(-32001); expect(body.error.message).toBe("Insufficient scope"); expect(body.error.data.error).toBe("insufficient_scope"); expect(body.error.data.required_scopes).toEqual(["read", "write"]); }); it("should use custom error_description in response body message", () => { const middleware = new AuthenticationMiddleware({ oauth: { protectedResource: { resource: "https://example.com", }, }, }); const response = middleware.getScopeChallengeResponse( ["admin"], "Admin privileges required", ); const body = JSON.parse(response.body); expect(body.error.message).toBe("Admin privileges required"); }); it("should handle single scope", () => { const middleware = new AuthenticationMiddleware({ oauth: { protectedResource: { resource: "https://example.com", }, }, }); const response = middleware.getScopeChallengeResponse(["admin"]); expect(response.headers["WWW-Authenticate"]).toContain('scope="admin"'); const body = JSON.parse(response.body); expect(body.error.data.required_scopes).toEqual(["admin"]); }); it("should handle multiple scopes", () => { const middleware = new AuthenticationMiddleware({ oauth: { protectedResource: { resource: "https://example.com", }, }, }); const response = middleware.getScopeChallengeResponse([ "read", "write", "admin", ]); expect(response.headers["WWW-Authenticate"]).toContain( 'scope="read write admin"', ); const body = JSON.parse(response.body); expect(body.error.data.required_scopes).toEqual([ "read", "write", "admin", ]); }); it("should not include WWW-Authenticate header without OAuth config", () => { const middleware = new AuthenticationMiddleware({}); const response = middleware.getScopeChallengeResponse(["admin"]); expect(response.headers["WWW-Authenticate"]).toBeUndefined(); expect(response.headers["Content-Type"]).toBe("application/json"); }); it("should return proper JSON-RPC 2.0 format", () => { const middleware = new AuthenticationMiddleware({ oauth: { protectedResource: { resource: "https://example.com", }, }, }); const response = middleware.getScopeChallengeResponse( ["read"], "Description", "req-123", ); const body = JSON.parse(response.body); expect(body.jsonrpc).toBe("2.0"); expect(body.id).toBe("req-123"); expect(body.error).toBeDefined(); expect(body.error.code).toBe(-32001); expect(body.error.message).toBe("Description"); expect(body.error.data).toBeDefined(); }); it("should include Content-Type header", () => { const middleware = new AuthenticationMiddleware({ oauth: { protectedResource: { resource: "https://example.com", }, }, }); const response = middleware.getScopeChallengeResponse(["read"]); expect(response.headers["Content-Type"]).toBe("application/json"); }); it("should handle empty scopes array", () => { const middleware = new AuthenticationMiddleware({ oauth: { protectedResource: { resource: "https://example.com", }, }, }); const response = middleware.getScopeChallengeResponse([]); expect(response.headers["WWW-Authenticate"]).toContain('scope=""'); const body = JSON.parse(response.body); expect(body.error.data.required_scopes).toEqual([]); }); }); });

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/Valerio357/bet-mcp'

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