mirror of
https://github.com/jjbrunton/Sauci.git
synced 2026-10-31 18:19:43 +00:00
Replace the Supabase application data plane with the Node/PostgreSQL API, migrate mobile, admin, web, and MCP callers, add controlled cutover tooling, and define hardened Dokploy infrastructure.
65 lines
2.3 KiB
TypeScript
65 lines
2.3 KiB
TypeScript
import { exportJWK, generateKeyPair, SignJWT } from 'jose';
|
|
import { describe, expect, it } from 'vitest';
|
|
import { createAuthVerifier } from '../src/auth.js';
|
|
import { loadConfig } from '../src/config.js';
|
|
|
|
const issuer = 'https://auth.sauci.test/auth/v1';
|
|
|
|
async function signedToken(audience = 'authenticated') {
|
|
const { publicKey, privateKey } = await generateKeyPair('ES256');
|
|
const publicJwk = await exportJWK(publicKey);
|
|
publicJwk.kid = 'test-key';
|
|
const token = await new SignJWT({
|
|
email: 'user@sauci.test',
|
|
user_metadata: { full_name: 'Test User', avatar_url: 'https://example.test/avatar.png' },
|
|
})
|
|
.setProtectedHeader({ alg: 'ES256', kid: 'test-key' })
|
|
.setSubject('22222222-2222-4222-8222-222222222222')
|
|
.setIssuer(issuer)
|
|
.setAudience(audience)
|
|
.setIssuedAt()
|
|
.setExpirationTime('5m')
|
|
.sign(privateKey);
|
|
return { token, jwks: JSON.stringify({ keys: [publicJwk] }) };
|
|
}
|
|
|
|
describe('Supabase Auth JWT verification', () => {
|
|
it('verifies issuer, audience, signature and maps identity claims', async () => {
|
|
const { token, jwks } = await signedToken();
|
|
const config = loadConfig({
|
|
NODE_ENV: 'test',
|
|
DATABASE_URL: 'postgresql://localhost/sauci_test',
|
|
SUPABASE_AUTH_ISSUER: issuer,
|
|
AUTH_TEST_JWKS: jwks,
|
|
});
|
|
|
|
await expect(createAuthVerifier(config).verify(token)).resolves.toEqual({
|
|
id: '22222222-2222-4222-8222-222222222222',
|
|
email: 'user@sauci.test',
|
|
name: 'Test User',
|
|
avatarUrl: 'https://example.test/avatar.png',
|
|
});
|
|
});
|
|
|
|
it('rejects a token for another audience', async () => {
|
|
const { token, jwks } = await signedToken('another-service');
|
|
const config = loadConfig({
|
|
NODE_ENV: 'test',
|
|
DATABASE_URL: 'postgresql://localhost/sauci_test',
|
|
SUPABASE_AUTH_ISSUER: issuer,
|
|
AUTH_TEST_JWKS: jwks,
|
|
});
|
|
await expect(createAuthVerifier(config).verify(token)).rejects.toThrow();
|
|
});
|
|
|
|
it('refuses test JWKS configuration outside the test environment', async () => {
|
|
const { jwks } = await signedToken();
|
|
expect(() => loadConfig({
|
|
NODE_ENV: 'production',
|
|
DATABASE_URL: 'postgresql://localhost/sauci',
|
|
SUPABASE_AUTH_ISSUER: issuer,
|
|
AUTH_TEST_JWKS: jwks,
|
|
})).toThrow('AUTH_TEST_JWKS is forbidden');
|
|
});
|
|
});
|