fix(auth): add HTTPS reverse proxy origin for Tailscale Serve
Browser accesses via HTTPS (Tailscale TLS termination) but trustedOrigins only had the HTTP variant from BETTER_AUTH_URL. deriveReverseProxyOrigins() now adds the HTTPS equivalent for non-localhost HTTP URLs. Fixes 'Invalid origin' error on /login. --- Build: pass | Tests: pass — 8 passed (1 file) --- Build: pass | Tests: pass — Tests 2079 passed (2079) --- Build: pass | Tests: pass — Tests 2080 passed (2080)
This commit is contained in:
parent
23a3edf06e
commit
54c74a9e22
2 changed files with 58 additions and 10 deletions
|
|
@ -84,6 +84,33 @@ describe('createAuth', () => {
|
|||
createRemoteAuth({} as never);
|
||||
const args = tailscaleBetterAuthMock.mock.calls.at(-1)?.[0];
|
||||
expect(args?.trustedOrigins).toContain('http://osa.taile682b7.ts.net:3100');
|
||||
expect(args?.trustedOrigins).toContain('https://osa.taile682b7.ts.net');
|
||||
});
|
||||
|
||||
it('does not add HTTPS variant for localhost BETTER_AUTH_URL', async () => {
|
||||
vi.resetModules();
|
||||
const localBetterAuthMock = vi.fn().mockReturnValue({});
|
||||
vi.doMock('./config.js', () => ({
|
||||
CONTROLPLANE_AUTH_MODE: 'local_trusted',
|
||||
CONTROLPLANE_API_PORT: 4000,
|
||||
CONTROLPLANE_EXPOSURE: 'internal',
|
||||
PLATFORM_INTERNAL_BASE: 'home.arpa',
|
||||
PLATFORM_INTERNAL_DOMAIN: 'ai.home.arpa',
|
||||
PLATFORM_PUBLIC_BASE: '',
|
||||
BETTER_AUTH_SECRET: 'test-secret',
|
||||
BETTER_AUTH_URL: 'http://localhost:4000',
|
||||
}));
|
||||
vi.doMock('./logger.js', () => ({
|
||||
logger: { debug: vi.fn(), info: vi.fn(), warn: vi.fn(), error: vi.fn() },
|
||||
}));
|
||||
vi.doMock('better-auth', () => ({
|
||||
betterAuth: localBetterAuthMock,
|
||||
}));
|
||||
const { createAuth: createLocalAuth } = await import('./auth.js');
|
||||
createLocalAuth({} as never);
|
||||
const args = localBetterAuthMock.mock.calls.at(-1)?.[0];
|
||||
expect(args?.trustedOrigins).not.toContain('https://localhost');
|
||||
expect(args?.trustedOrigins).toContain('http://localhost:4000');
|
||||
});
|
||||
|
||||
it('includes the public controlplane origin when publicly exposed', async () => {
|
||||
|
|
|
|||
41
src/auth.ts
41
src/auth.ts
|
|
@ -23,6 +23,23 @@ function getBetterAuthBaseOrigin(): string | null {
|
|||
}
|
||||
}
|
||||
|
||||
function deriveReverseProxyOrigins(): string[] {
|
||||
const origins: string[] = [];
|
||||
try {
|
||||
const url = new URL(BETTER_AUTH_URL);
|
||||
if (
|
||||
url.protocol === 'http:' &&
|
||||
url.hostname !== 'localhost' &&
|
||||
url.hostname !== '127.0.0.1'
|
||||
) {
|
||||
origins.push(`https://${url.hostname}`);
|
||||
}
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
return origins;
|
||||
}
|
||||
|
||||
function assertControlplaneAuthConfiguration(): void {
|
||||
if (
|
||||
CONTROLPLANE_EXPOSURE === 'public' &&
|
||||
|
|
@ -46,17 +63,21 @@ function assertControlplaneAuthConfiguration(): void {
|
|||
export function createAuth(pool: Pool) {
|
||||
assertControlplaneAuthConfiguration();
|
||||
const betterAuthBaseOrigin = getBetterAuthBaseOrigin();
|
||||
const reverseProxyOrigins = deriveReverseProxyOrigins();
|
||||
|
||||
const trustedOrigins = Array.from(new Set([
|
||||
`http://localhost:${CONTROLPLANE_API_PORT}`,
|
||||
`http://${PLATFORM_INTERNAL_DOMAIN}:${CONTROLPLANE_API_PORT}`,
|
||||
`http://10.0.0.2:${CONTROLPLANE_API_PORT}`,
|
||||
`http://ai.${PLATFORM_INTERNAL_BASE}:${CONTROLPLANE_API_PORT}`,
|
||||
...(betterAuthBaseOrigin ? [betterAuthBaseOrigin] : []),
|
||||
...(PLATFORM_PUBLIC_BASE && CONTROLPLANE_EXPOSURE === 'public'
|
||||
? [`https://ai.${PLATFORM_PUBLIC_BASE}`]
|
||||
: []),
|
||||
]));
|
||||
const trustedOrigins = Array.from(
|
||||
new Set([
|
||||
`http://localhost:${CONTROLPLANE_API_PORT}`,
|
||||
`http://${PLATFORM_INTERNAL_DOMAIN}:${CONTROLPLANE_API_PORT}`,
|
||||
`http://10.0.0.2:${CONTROLPLANE_API_PORT}`,
|
||||
`http://ai.${PLATFORM_INTERNAL_BASE}:${CONTROLPLANE_API_PORT}`,
|
||||
...(betterAuthBaseOrigin ? [betterAuthBaseOrigin] : []),
|
||||
...reverseProxyOrigins,
|
||||
...(PLATFORM_PUBLIC_BASE && CONTROLPLANE_EXPOSURE === 'public'
|
||||
? [`https://ai.${PLATFORM_PUBLIC_BASE}`]
|
||||
: []),
|
||||
]),
|
||||
);
|
||||
|
||||
const auth = betterAuth({
|
||||
baseURL: BETTER_AUTH_URL,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue