Skip to main content
Glama
authentication.test.js12.2 kB
import { vi } from "vitest"; import { AuthenticationManager } from "@/client/managers/AuthenticationManager.js"; import { AuthenticationError } from "@/types/client.js"; describe("AuthenticationManager", () => { let authManager; let mockConfig; beforeEach(() => { mockConfig = { siteUrl: "https://example.com", username: "testuser", appPassword: "test-app-password", authMethod: "app-password", }; authManager = new AuthenticationManager(mockConfig); }); describe("constructor", () => { it("should initialize with valid config", () => { expect(authManager.config).toEqual(mockConfig); }); it("should throw error with invalid config", () => { expect(() => { new AuthenticationManager({}); }).toThrow("Site URL is required"); }); it("should validate authentication method", () => { expect(() => { new AuthenticationManager({ siteUrl: "https://example.com", authMethod: "invalid-method", }); }).toThrow("Invalid authentication method"); }); }); describe("getAuthHeaders", () => { it("should return app-password headers", () => { const headers = authManager.getAuthHeaders(); expect(headers).toEqual({ Authorization: `Basic ${Buffer.from("testuser:test-app-password").toString("base64")}`, }); }); it("should return JWT headers", () => { authManager.config.authMethod = "jwt"; authManager.config.jwtToken = "test-jwt-token"; const headers = authManager.getAuthHeaders(); expect(headers).toEqual({ Authorization: "Bearer test-jwt-token", }); }); it("should return API key headers", () => { authManager.config.authMethod = "api-key"; authManager.config.apiKey = "test-api-key"; const headers = authManager.getAuthHeaders(); expect(headers).toEqual({ "X-API-Key": "test-api-key", }); }); it("should return basic auth headers", () => { authManager.config.authMethod = "basic"; authManager.config.password = "test-password"; const headers = authManager.getAuthHeaders(); expect(headers).toEqual({ Authorization: `Basic ${Buffer.from("testuser:test-password").toString("base64")}`, }); }); it("should throw error for JWT without token", () => { authManager.config.authMethod = "jwt"; authManager.config.jwtToken = null; expect(() => { authManager.getAuthHeaders(); }).toThrow(AuthenticationError); }); it("should throw error for API key without key", () => { authManager.config.authMethod = "api-key"; authManager.config.apiKey = null; expect(() => { authManager.getAuthHeaders(); }).toThrow(AuthenticationError); }); }); describe("validateCredentials", () => { it("should validate app-password credentials", () => { expect(() => { authManager.validateCredentials(); }).not.toThrow(); }); it("should validate JWT credentials", () => { authManager.config.authMethod = "jwt"; authManager.config.jwtToken = "valid-token"; expect(() => { authManager.validateCredentials(); }).not.toThrow(); }); it("should throw error for missing username", () => { authManager.config.username = null; expect(() => { authManager.validateCredentials(); }).toThrow("Username is required"); }); it("should throw error for missing app password", () => { authManager.config.appPassword = null; expect(() => { authManager.validateCredentials(); }).toThrow("App password is required"); }); it("should throw error for missing JWT token", () => { authManager.config.authMethod = "jwt"; authManager.config.jwtToken = null; expect(() => { authManager.validateCredentials(); }).toThrow("JWT token is required"); }); it("should throw error for missing API key", () => { authManager.config.authMethod = "api-key"; authManager.config.apiKey = null; expect(() => { authManager.validateCredentials(); }).toThrow("API key is required"); }); it("should throw error for missing basic password", () => { authManager.config.authMethod = "basic"; authManager.config.password = null; expect(() => { authManager.validateCredentials(); }).toThrow("Password is required"); }); }); describe("updateAuthMethod", () => { it("should update to JWT authentication", () => { authManager.updateAuthMethod("jwt", { jwtToken: "new-jwt-token", }); expect(authManager.config.authMethod).toBe("jwt"); expect(authManager.config.jwtToken).toBe("new-jwt-token"); }); it("should update to API key authentication", () => { authManager.updateAuthMethod("api-key", { apiKey: "new-api-key", }); expect(authManager.config.authMethod).toBe("api-key"); expect(authManager.config.apiKey).toBe("new-api-key"); }); it("should update to basic authentication", () => { authManager.updateAuthMethod("basic", { username: "newuser", password: "newpass", }); expect(authManager.config.authMethod).toBe("basic"); expect(authManager.config.username).toBe("newuser"); expect(authManager.config.password).toBe("newpass"); }); it("should throw error for invalid method", () => { expect(() => { authManager.updateAuthMethod("invalid", {}); }).toThrow("Invalid authentication method"); }); it("should throw error for missing JWT token", () => { expect(() => { authManager.updateAuthMethod("jwt", {}); }).toThrow("JWT token is required"); }); it("should throw error for missing API key", () => { expect(() => { authManager.updateAuthMethod("api-key", {}); }).toThrow("API key is required"); }); }); describe("refreshToken", () => { it("should refresh JWT token", async () => { authManager.config.authMethod = "jwt"; authManager.config.jwtToken = "old-token"; authManager.config.refreshToken = "refresh-token"; // Mock the refresh API call const mockRefresh = vi.fn().mockResolvedValue({ token: "new-jwt-token", expires_in: 3600, }); authManager.refreshJwtToken = mockRefresh; await authManager.refreshToken(); expect(mockRefresh).toHaveBeenCalled(); expect(authManager.config.jwtToken).toBe("new-jwt-token"); }); it("should handle refresh token errors", async () => { authManager.config.authMethod = "jwt"; authManager.config.refreshToken = "invalid-refresh-token"; const mockRefresh = vi.fn().mockRejectedValue(new Error("Invalid refresh token")); authManager.refreshJwtToken = mockRefresh; await expect(authManager.refreshToken()).rejects.toThrow("Invalid refresh token"); }); it("should not refresh non-JWT auth methods", async () => { authManager.config.authMethod = "app-password"; await expect(authManager.refreshToken()).rejects.toThrow("Token refresh not supported"); }); }); describe("isTokenExpired", () => { it("should check if JWT token is expired", () => { authManager.config.authMethod = "jwt"; authManager.config.jwtToken = "token"; authManager.config.tokenExpiry = Date.now() - 1000; // Expired 1 second ago expect(authManager.isTokenExpired()).toBe(true); }); it("should check if JWT token is not expired", () => { authManager.config.authMethod = "jwt"; authManager.config.jwtToken = "token"; authManager.config.tokenExpiry = Date.now() + 60000; // Expires in 1 minute expect(authManager.isTokenExpired()).toBe(false); }); it("should return false for non-JWT auth methods", () => { authManager.config.authMethod = "app-password"; expect(authManager.isTokenExpired()).toBe(false); }); it("should return true if no expiry set for JWT", () => { authManager.config.authMethod = "jwt"; authManager.config.jwtToken = "token"; authManager.config.tokenExpiry = null; expect(authManager.isTokenExpired()).toBe(true); }); }); describe("getAuthStatus", () => { it("should return auth status for app-password", () => { const status = authManager.getAuthStatus(); expect(status).toEqual({ method: "app-password", username: "testuser", isAuthenticated: true, tokenExpired: false, }); }); it("should return auth status for JWT", () => { authManager.config.authMethod = "jwt"; authManager.config.jwtToken = "valid-token"; authManager.config.tokenExpiry = Date.now() + 60000; const status = authManager.getAuthStatus(); expect(status).toEqual({ method: "jwt", username: "testuser", isAuthenticated: true, tokenExpired: false, tokenExpiry: expect.any(Number), }); }); it("should return status for expired JWT", () => { authManager.config.authMethod = "jwt"; authManager.config.jwtToken = "expired-token"; authManager.config.tokenExpiry = Date.now() - 1000; const status = authManager.getAuthStatus(); expect(status.isAuthenticated).toBe(false); expect(status.tokenExpired).toBe(true); }); }); describe("edge cases", () => { it("should handle empty site URL", () => { expect(() => { new AuthenticationManager({ siteUrl: "", username: "user", appPassword: "pass", }); }).toThrow("Site URL is required"); }); it("should handle malformed site URL", () => { expect(() => { new AuthenticationManager({ siteUrl: "not-a-url", username: "user", appPassword: "pass", }); }).toThrow("Invalid site URL"); }); it("should handle null credentials", () => { const manager = new AuthenticationManager({ siteUrl: "https://example.com", username: null, appPassword: null, authMethod: "app-password", }); expect(() => { manager.validateCredentials(); }).toThrow("Username is required"); }); it("should handle very long credentials", () => { const longPassword = "a".repeat(10000); const manager = new AuthenticationManager({ siteUrl: "https://example.com", username: "user", appPassword: longPassword, authMethod: "app-password", }); const headers = manager.getAuthHeaders(); expect(headers.Authorization).toBeDefined(); }); it("should handle special characters in credentials", () => { const specialPassword = "pass@#$%^&*()_+-=[]{}|;:,.<>?"; const manager = new AuthenticationManager({ siteUrl: "https://example.com", username: "user", appPassword: specialPassword, authMethod: "app-password", }); const headers = manager.getAuthHeaders(); const decoded = Buffer.from(headers.Authorization.split(" ")[1], "base64").toString(); expect(decoded).toBe(`user:${specialPassword}`); }); it("should handle unicode characters in credentials", () => { const unicodePassword = "pässwörd123"; const manager = new AuthenticationManager({ siteUrl: "https://example.com", username: "user", appPassword: unicodePassword, authMethod: "app-password", }); const headers = manager.getAuthHeaders(); expect(headers.Authorization).toBeDefined(); }); it("should handle concurrent auth header requests", () => { const promises = []; for (let i = 0; i < 100; i++) { promises.push(Promise.resolve(authManager.getAuthHeaders())); } return Promise.all(promises).then((results) => { expect(results).toHaveLength(100); results.forEach((headers) => { expect(headers.Authorization).toBeDefined(); }); }); }); }); });

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/docdyhr/mcp-wordpress'

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