Something went wrong. Try again.
AtAuth
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190/** * Forward-Auth Proxy Utilities Tests */import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest';import { createSessionCookie, verifySessionCookie, createProxyCookie, verifyProxyCookie, createAuthTicket, verifyAuthTicket, parseCookies, isAllowedRedirect, extractOrigin, SESSION_COOKIE_NAME, PROXY_COOKIE_NAME,} from './proxy-auth.js';
const TEST_SECRET = 'test-secret-for-hmac-signing-32b!';
describe('Session Cookie', () => { it('should create and verify a session cookie', () => { const cookie = createSessionCookie('session-123', TEST_SECRET, 3600); const result = verifySessionCookie(cookie, TEST_SECRET); expect(result).toBe('session-123'); });
it('should reject an expired cookie', () => { vi.useFakeTimers(); const cookie = createSessionCookie('session-123', TEST_SECRET, 60); // Advance past expiry vi.advanceTimersByTime(61 * 1000); const result = verifySessionCookie(cookie, TEST_SECRET); expect(result).toBeNull(); vi.useRealTimers(); });
it('should reject a tampered cookie', () => { const cookie = createSessionCookie('session-123', TEST_SECRET, 3600); const tampered = cookie.slice(0, -1) + 'x'; const result = verifySessionCookie(tampered, TEST_SECRET); expect(result).toBeNull(); });
it('should reject a cookie with wrong secret', () => { const cookie = createSessionCookie('session-123', TEST_SECRET, 3600); const result = verifySessionCookie(cookie, 'wrong-secret'); expect(result).toBeNull(); });
it('should reject malformed cookies', () => { expect(verifySessionCookie('', TEST_SECRET)).toBeNull(); expect(verifySessionCookie('no-dots', TEST_SECRET)).toBeNull(); expect(verifySessionCookie('too.many.dots', TEST_SECRET)).toBeNull(); expect(verifySessionCookie('invalid.base64!', TEST_SECRET)).toBeNull(); });});
describe('Proxy Cookie', () => { it('should create and verify (same as session cookie format)', () => { const cookie = createProxyCookie('session-456', TEST_SECRET, 86400); const result = verifyProxyCookie(cookie, TEST_SECRET); expect(result).toBe('session-456'); });});
describe('Auth Ticket', () => { it('should create and verify an auth ticket', () => { const ticket = createAuthTicket( 'session-789', 'did:plc:abc123', 'user.bsky.social', 'https://search.arcnode.xyz', TEST_SECRET, ); const result = verifyAuthTicket(ticket, TEST_SECRET); expect(result).not.toBeNull(); expect(result!.sid).toBe('session-789'); expect(result!.did).toBe('did:plc:abc123'); expect(result!.handle).toBe('user.bsky.social'); expect(result!.origin).toBe('https://search.arcnode.xyz'); });
it('should reject an expired ticket', () => { vi.useFakeTimers(); const ticket = createAuthTicket( 'session-789', 'did:plc:abc123', 'user.bsky.social', 'https://search.arcnode.xyz', TEST_SECRET, ); // Advance past 60s expiry vi.advanceTimersByTime(61 * 1000); const result = verifyAuthTicket(ticket, TEST_SECRET); expect(result).toBeNull(); vi.useRealTimers(); });
it('should reject a ticket with wrong origin', () => { const ticket = createAuthTicket( 'session-789', 'did:plc:abc123', 'user.bsky.social', 'https://search.arcnode.xyz', TEST_SECRET, ); const result = verifyAuthTicket(ticket, TEST_SECRET, 'https://evil.example.com'); expect(result).toBeNull(); });
it('should accept a ticket with matching expected origin', () => { const ticket = createAuthTicket( 'session-789', 'did:plc:abc123', 'user.bsky.social', 'https://search.arcnode.xyz', TEST_SECRET, ); const result = verifyAuthTicket(ticket, TEST_SECRET, 'https://search.arcnode.xyz'); expect(result).not.toBeNull(); expect(result!.sid).toBe('session-789'); });
it('should reject a tampered ticket', () => { const ticket = createAuthTicket( 'session-789', 'did:plc:abc123', 'user.bsky.social', 'https://search.arcnode.xyz', TEST_SECRET, ); const tampered = ticket.slice(0, -1) + 'x'; const result = verifyAuthTicket(tampered, TEST_SECRET); expect(result).toBeNull(); });});
describe('parseCookies', () => { it('should parse a standard cookie header', () => { const result = parseCookies('foo=bar; baz=qux'); expect(result).toEqual({ foo: 'bar', baz: 'qux' }); });
it('should handle cookies with = in the value', () => { const result = parseCookies('token=abc=def=ghi'); expect(result).toEqual({ token: 'abc=def=ghi' }); });
it('should return empty object for undefined', () => { expect(parseCookies(undefined)).toEqual({}); });
it('should return empty object for empty string', () => { expect(parseCookies('')).toEqual({}); });
it('should trim whitespace', () => { const result = parseCookies(' foo = bar ; baz = qux '); expect(result).toEqual({ foo: 'bar', baz: 'qux' }); });});
describe('isAllowedRedirect', () => { const allowed = ['https://search.arcnode.xyz', 'https://element.arcnode.xyz'];
it('should allow a URL with an allowed origin', () => { expect(isAllowedRedirect('https://search.arcnode.xyz/some/path', allowed)).toBe(true); expect(isAllowedRedirect('https://element.arcnode.xyz/', allowed)).toBe(true); });
it('should reject a URL with a disallowed origin', () => { expect(isAllowedRedirect('https://evil.example.com/search', allowed)).toBe(false); });
it('should reject an invalid URL', () => { expect(isAllowedRedirect('not-a-url', allowed)).toBe(false); });
it('should reject a URL with different port', () => { expect(isAllowedRedirect('https://search.arcnode.xyz:8443/path', allowed)).toBe(false); });
it('should reject a URL with different scheme', () => { expect(isAllowedRedirect('http://search.arcnode.xyz/path', allowed)).toBe(false); });});
describe('extractOrigin', () => { it('should extract origin from a full URL', () => { expect(extractOrigin('https://search.arcnode.xyz/some/path?q=test')).toBe('https://search.arcnode.xyz'); });
it('should return null for invalid URL', () => { expect(extractOrigin('not-a-url')).toBeNull(); });});
describe('Cookie names', () => { it('should export expected cookie names', () => { expect(SESSION_COOKIE_NAME).toBe('_atauth_session'); expect(PROXY_COOKIE_NAME).toBe('_atauth_proxy'); });});