diff --git a/apps/api/src/auth/auth.controller.spec.ts b/apps/api/src/auth/auth.controller.spec.ts index 079d498..764b5ca 100644 --- a/apps/api/src/auth/auth.controller.spec.ts +++ b/apps/api/src/auth/auth.controller.spec.ts @@ -157,6 +157,77 @@ describe("AuthController", () => { type: "credentials", }); }); + + it("should never leak secrets in auth config response", () => { + // Set ALL sensitive environment variables with known values + const sensitiveEnv: Record = { + OIDC_CLIENT_SECRET: "test-client-secret", + OIDC_CLIENT_ID: "test-client-id", + OIDC_ISSUER: "https://auth.test.com/", + OIDC_REDIRECT_URI: "https://app.test.com/auth/callback/authentik", + BETTER_AUTH_SECRET: "test-better-auth-secret", + JWT_SECRET: "test-jwt-secret", + CSRF_SECRET: "test-csrf-secret", + DATABASE_URL: "postgresql://user:password@localhost/db", + OIDC_ENABLED: "true", + }; + + const originalEnv: Record = {}; + for (const [key, value] of Object.entries(sensitiveEnv)) { + originalEnv[key] = process.env[key]; + process.env[key] = value; + } + + try { + // Mock the service to return a realistic config with both providers + const mockConfig = { + providers: [ + { id: "email", name: "Email", type: "credentials" as const }, + { id: "authentik", name: "Authentik", type: "oauth" as const }, + ], + }; + mockAuthService.getAuthConfig.mockReturnValue(mockConfig); + + const result = controller.getConfig(); + const serialized = JSON.stringify(result); + + // Assert no secret values leak into the serialized response + const forbiddenPatterns = [ + "test-client-secret", + "test-client-id", + "test-better-auth-secret", + "test-jwt-secret", + "test-csrf-secret", + "auth.test.com", + "callback", + "password", + ]; + + for (const pattern of forbiddenPatterns) { + expect(serialized).not.toContain(pattern); + } + + // Assert response contains ONLY expected fields + expect(result).toHaveProperty("providers"); + expect(Object.keys(result)).toEqual(["providers"]); + expect(Array.isArray(result.providers)).toBe(true); + + for (const provider of result.providers) { + const keys = Object.keys(provider); + expect(keys).toEqual(expect.arrayContaining(["id", "name", "type"])); + expect(keys).toHaveLength(3); + } + } finally { + // Restore original environment + for (const [key] of Object.entries(sensitiveEnv)) { + if (originalEnv[key] === undefined) { + delete process.env[key]; + } else { + process.env[key] = originalEnv[key]; + } + } + } + }); }); describe("getSession", () => {