import { afterEach, describe, expect, it, vi } from 'vitest'; import { NextRequest, NextResponse } from 'next/server'; import { getAppBaseUrl, getVkRedirectUri } from '../src/lib/auth/app-config'; import { setSessionCookie, clearSessionCookie } from '../src/lib/auth/session'; import { validateCsrfOrigin } from '../src/lib/auth/csrf-guard'; afterEach(() => vi.unstubAllEnvs()); function config(base: string, profile = 'local-single-user') { vi.stubEnv('NODE_ENV', 'production'); vi.stubEnv('DEPLOYMENT_PROFILE', profile); vi.stubEnv('APP_BASE_URL', base); vi.stubEnv('VK_REDIRECT_URI', `${base}/api/auth/vk/callback`); } describe('production deployment profiles', () => { it('allows HTTP only in the explicit loopback profile and uses HttpOnly Lax cookies', () => { config('http://localhost:3100'); expect(getAppBaseUrl()).toBe('http://localhost:3100'); expect(getVkRedirectUri()).toBe('http://localhost:3100/api/auth/vk/callback'); const res = NextResponse.json({}); setSessionCookie(res, 'fake-session'); expect(res.headers.get('set-cookie')).toContain('HttpOnly'); expect(res.headers.get('set-cookie')).toContain('SameSite=lax'); expect(res.headers.get('set-cookie')).not.toContain('Secure'); clearSessionCookie(res); expect(res.headers.get('set-cookie')).not.toContain('Secure'); }); it.each(['http://evil.test', 'http://localhost.evil.test', 'http://192.168.1.81:3100', 'https://localhost:3100', 'http://localhost:3100/path'])('rejects invalid local origin %s', (base) => { config(base); expect(() => getAppBaseUrl()).toThrow(); }); it('keeps strict HTTPS and Secure cookies outside the local profile', () => { config('http://localhost:3100', 'strict'); expect(() => getAppBaseUrl()).toThrow(); config('https://random.ochenstarik.ru', 'strict'); expect(getAppBaseUrl()).toBe('https://random.ochenstarik.ru'); const res = NextResponse.json({}); setSessionCookie(res, 'fake-session'); expect(res.headers.get('set-cookie')).toContain('Secure'); }); it('rejects redirect origin and path mismatch', () => { config('http://localhost:3100'); vi.stubEnv('VK_REDIRECT_URI', 'http://localhost:3101/api/auth/vk/callback'); expect(() => getVkRedirectUri()).toThrow(); vi.stubEnv('VK_REDIRECT_URI', 'http://localhost:3100/other'); expect(() => getVkRedirectUri()).toThrow(); }); it('ignores forged Host/forwarded headers and rejects scheme downgrade for CSRF', () => { config('https://random.ochenstarik.ru', 'strict'); const request = (origin: string) => new NextRequest('https://random.ochenstarik.ru/api/giveaways', { method: 'POST', headers: { origin, host: 'evil.test', 'x-forwarded-host': 'evil.test' }, }); expect(() => validateCsrfOrigin(request('https://evil.test'))).toThrow(); expect(() => validateCsrfOrigin(request('http://random.ochenstarik.ru'))).toThrow(); expect(() => validateCsrfOrigin(request('https://random.ochenstarik.ru'))).not.toThrow(); }); });