[grade=B] feat(auth): onboard missing credentials into encrypted vault
CI / Test & Lint (push) Canceled after 0s
CI / Security audit (push) Canceled after 0s

This commit is contained in:
Hermes
2026-08-22 05:41:38 -07:00
parent d313b1e872
commit 84edb035e3
24 changed files with 959 additions and 235 deletions
@@ -51,10 +51,15 @@ class CaddyfileGenerator {
_authSnippet(apiPort) {
return `# DashCaddy SSO auth snippet
(dashcaddy_auth) {
forward_auth localhost:${apiPort} {
@needsAuth not path /dashcaddy-sso
forward_auth @needsAuth localhost:${apiPort} {
uri /api/v1/auth/gate/{args[0]}
copy_headers Authorization X-Api-Key X-App-Cookie X-Emby-Token X-Plex-Token
}
handle /dashcaddy-sso {
rewrite * /api/v1/auth/sso-exchange
reverse_proxy localhost:${apiPort}
}
}
`;
}
@@ -0,0 +1,35 @@
const fs = require('fs');
const path = require('path');
const { spawnSync } = require('child_process');
const CaddyfileGenerator = require('./caddyfile-generator');
describe('cross-host SSO installer contract', () => {
test('generated auth snippet exposes the public one-time exchange landing route', () => {
const snippet = new CaddyfileGenerator()._authSnippet(3001);
expect(snippet).toContain('@needsAuth not path /dashcaddy-sso');
expect(snippet).toContain('handle /dashcaddy-sso');
expect(snippet).toContain('rewrite * /api/v1/auth/sso-exchange');
expect(snippet).toContain('reverse_proxy localhost:3001');
});
test('shell installer emits the same exchange landing contract', () => {
const installer = fs.readFileSync(path.join(__dirname, '..', '..', 'install.sh'), 'utf8');
expect(installer).toContain('@needsAuth not path /dashcaddy-sso');
expect(installer).toContain('handle /dashcaddy-sso');
expect(installer).toContain('rewrite * /api/v1/auth/sso-exchange');
});
test('Caddy parser accepts a complete service config using the generated snippet', () => {
const available = spawnSync('caddy', ['version'], { encoding: 'utf8' });
if (available.status !== 0) return;
const generator = new CaddyfileGenerator();
const config = `${generator._authSnippet(3001)}\nexample.test {\n import dashcaddy_auth plex\n respond "ok" 200\n}\n`;
const result = spawnSync('caddy', ['validate', '--config', '-', '--adapter', 'caddyfile'], {
input: config,
encoding: 'utf8',
});
expect(result.status).toBe(0);
expect(`${result.stdout}\n${result.stderr}`).toContain('Valid configuration');
});
});