Spaces:
Paused
Paused
| import { describe, it, expect, afterEach, vi } from 'vitest'; | |
| import request from 'supertest'; | |
| import app from '../../src/app.js'; | |
| import { assertProdConfig } from '../../src/utils/network/auth.util.js'; | |
| // non-local test client | |
| const REMOTE = '203.0.113.5'; | |
| describe('inbound API key auth', () => { | |
| afterEach(() => { | |
| vi.unstubAllEnvs(); | |
| }); | |
| it('is disabled when API_KEY is unset', async () => { | |
| vi.stubEnv('API_KEY', ''); | |
| const res = await request(app).get('/proxy').set('X-Forwarded-For', REMOTE); | |
| expect(res.status).toBe(403); | |
| }); | |
| it('returns 401 for a remote request with no key', async () => { | |
| vi.stubEnv('API_KEY', 'secret'); | |
| const res = await request(app).get('/proxy').set('X-Forwarded-For', REMOTE); | |
| expect(res.status).toBe(401); | |
| }); | |
| it('returns 401 for a wrong key', async () => { | |
| vi.stubEnv('API_KEY', 'secret'); | |
| const res = await request(app) | |
| .get('/proxy') | |
| .set('X-Forwarded-For', REMOTE) | |
| .set('x-api-key', 'nope'); | |
| expect(res.status).toBe(401); | |
| }); | |
| it('accepts a correct key header (then hits the 403 sig gate)', async () => { | |
| vi.stubEnv('API_KEY', 'secret'); | |
| const res = await request(app) | |
| .get('/proxy') | |
| .set('X-Forwarded-For', REMOTE) | |
| .set('x-api-key', 'secret'); | |
| expect(res.status).toBe(403); | |
| }); | |
| it('accepts a correct ?key= query', async () => { | |
| vi.stubEnv('API_KEY', 'secret'); | |
| const res = await request(app) | |
| .get('/proxy?key=secret') | |
| .set('X-Forwarded-For', REMOTE); | |
| expect(res.status).toBe(403); | |
| }); | |
| it('exempts localhost even with no key', async () => { | |
| vi.stubEnv('API_KEY', 'secret'); | |
| const res = await request(app).get('/proxy'); | |
| expect(res.status).toBe(403); | |
| }); | |
| }); | |
| describe('localhost bypass cannot be spoofed via header', () => { | |
| afterEach(() => vi.unstubAllEnvs()); | |
| it('rejects a spoofed X-Forwarded-For: 127.0.0.1', async () => { | |
| vi.stubEnv('API_KEY', 'secret'); | |
| const res = await request(app) | |
| .get('/proxy') | |
| .set('X-Forwarded-For', '127.0.0.1'); | |
| expect(res.status).toBe(401); | |
| }); | |
| }); | |
| describe('assertProdConfig', () => { | |
| it('passes in production without API_KEY (auth disabled)', () => { | |
| expect(() => | |
| assertProdConfig({ | |
| NODE_ENV: 'production', | |
| PROXY_SIGNING_SECRET: 's', | |
| } as NodeJS.ProcessEnv) | |
| ).not.toThrow(); | |
| }); | |
| it('throws in production without PROXY_SIGNING_SECRET', () => { | |
| expect(() => | |
| assertProdConfig({ | |
| NODE_ENV: 'production', | |
| API_KEY: 'x', | |
| } as NodeJS.ProcessEnv) | |
| ).toThrow(); | |
| }); | |
| it('passes in production with API_KEY and PROXY_SIGNING_SECRET', () => { | |
| expect(() => | |
| assertProdConfig({ | |
| NODE_ENV: 'production', | |
| API_KEY: 'x', | |
| PROXY_SIGNING_SECRET: 's', | |
| } as NodeJS.ProcessEnv) | |
| ).not.toThrow(); | |
| }); | |
| it('passes outside production', () => { | |
| expect(() => | |
| assertProdConfig({ NODE_ENV: 'development' } as NodeJS.ProcessEnv) | |
| ).not.toThrow(); | |
| }); | |
| }); | |