Files
0pt/tests/auth/context.test.ts
T
SIAX Foundation BotandClaude Opus 4.8 1d76d50f3d
CI (SIAX Cloud) / security (push) Failing after 28s
CI (SIAX Cloud) / quality (push) Failing after 44s
CI (SIAX Cloud) / security (pull_request) Failing after 26s
CI (SIAX Cloud) / quality (pull_request) Failing after 33s
feat(auth,foundation): Wave 2 flag-gated Zitadel JWT verify + validation + eslint + tests
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-25 14:32:34 +02:00

119 lines
3.9 KiB
TypeScript

/**
* Unit tests for src/auth/context.ts `resolveAuthContext` -- the flag-gated
* auth seam. Verification is injected (opts.verify) so these tests are pure
* and network-free; they exercise the decision logic in both AUTH_ENFORCE
* modes.
*/
import { describe, it, expect, vi } from 'vitest';
import { resolveAuthContext, type OptRequestContext } from '@/src/auth/context';
import type { VerifiedPrincipal } from '@/src/auth/zitadel';
const principal: VerifiedPrincipal = {
sub: 'user_1',
tenantId: 'tenant_x',
claims: { sub: 'user_1', iss: 'https://id-customers.siax.io' },
};
const okVerify = vi.fn(async () => principal);
const failVerify = vi.fn(async () => {
throw new Error('token_verification_failed');
});
function h(init: Record<string, string>): Headers {
return new Headers(init);
}
describe('resolveAuthContext -- enforce mode', () => {
it('401s when no bearer token is present', async () => {
const d = await resolveAuthContext(h({ 'x-tenant-id': 'tenant_x' }), { enforce: true, verify: okVerify });
expect(d.ok).toBe(false);
if (!d.ok) {
expect(d.status).toBe(401);
expect(d.code).toBe('OPT_UNAUTHENTICATED');
}
});
it('401s when the token fails verification', async () => {
const d = await resolveAuthContext(h({ authorization: 'Bearer bad.tok.en' }), {
enforce: true,
verify: failVerify,
});
expect(d.ok).toBe(false);
if (!d.ok) expect(d.status).toBe(401);
});
it('attaches the verified principal and derives tenant from the TOKEN', async () => {
const d = await resolveAuthContext(h({ authorization: 'Bearer good.tok.en' }), {
enforce: true,
verify: okVerify,
});
expect(d.ok).toBe(true);
if (d.ok) {
expect(d.ctx.principal).toEqual(principal);
expect(d.ctx.tenantId).toBe('tenant_x');
expect(d.ctx.actorId).toBe('user_1');
}
});
it('403s when X-Tenant-Id disagrees with the token tenant', async () => {
const d = await resolveAuthContext(
h({ authorization: 'Bearer good.tok.en', 'x-tenant-id': 'tenant_evil' }),
{ enforce: true, verify: okVerify },
);
expect(d.ok).toBe(false);
if (!d.ok) {
expect(d.status).toBe(403);
expect(d.code).toBe('OPT_ACCESS_DENIED');
expect(d.details).toMatchObject({ header_tenant: 'tenant_evil', token_tenant: 'tenant_x' });
}
});
it('allows a matching X-Tenant-Id', async () => {
const d = await resolveAuthContext(
h({ authorization: 'Bearer good.tok.en', 'x-tenant-id': 'tenant_x' }),
{ enforce: true, verify: okVerify },
);
expect(d.ok).toBe(true);
});
});
describe('resolveAuthContext -- non-enforce (default) mode', () => {
it('never rejects when no token is present', async () => {
const d = await resolveAuthContext(h({ 'x-tenant-id': 'tenant_header' }), {
enforce: false,
verify: okVerify,
});
expect(d.ok).toBe(true);
if (d.ok) {
expect((d.ctx as OptRequestContext).principal).toBeUndefined();
expect(d.ctx.tenantId).toBe('tenant_header');
}
});
it('never rejects even when a present token fails verification (logs a warning)', async () => {
const logger = { warn: vi.fn() };
const d = await resolveAuthContext(h({ authorization: 'Bearer bad.tok.en' }), {
enforce: false,
verify: failVerify,
logger,
});
expect(d.ok).toBe(true);
if (d.ok) expect(d.ctx.principal).toBeUndefined();
expect(logger.warn).toHaveBeenCalledOnce();
});
it('attaches the principal when a present token verifies, without overriding a supplied tenant', async () => {
const d = await resolveAuthContext(
h({ authorization: 'Bearer good.tok.en', 'x-tenant-id': 'tenant_header' }),
{ enforce: false, verify: okVerify },
);
expect(d.ok).toBe(true);
if (d.ok) {
expect(d.ctx.principal).toEqual(principal);
// non-breaking: caller-supplied header tenant is preserved
expect(d.ctx.tenantId).toBe('tenant_header');
}
});
});