diff --git a/README.md b/README.md index 0c8c516..d081570 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,10 @@ server has without hardcoding any of them. mail server itself. INBUXA Admin is its own deployment, pointed at the server either at build time (`VITE_API_BASE_URL`) or at deploy time: `` in - `index.html`. + `index.html`. Hosted like that, it signs in as the OAuth client + `inbuxa-admin`, which the server registers when it's started with + `INBUXA_ADMIN_URL` set to INBUXA Admin's address (for development, + `http://localhost:5173`). - **INBUXA's look:** the logo and ihasmail's palette. - **Two-factor setup** names INBUXA as the issuer, and no longer makes authenticator apps fetch a logo from a third-party site. diff --git a/src/lib/oauthClientId.test.ts b/src/lib/oauthClientId.test.ts index 4c0db44..922de26 100644 --- a/src/lib/oauthClientId.test.ts +++ b/src/lib/oauthClientId.test.ts @@ -46,6 +46,20 @@ describe('getOAuthClientId', () => { expect(getOAuthClientId()).toBe('stalwart-webui'); }); + it('is inbuxa-admin when hosted apart from the server', async () => { + const getOAuthClientId = await loadWithMeta( + '', + ); + expect(getOAuthClientId()).toBe('inbuxa-admin'); + }); + + it('still prefers an injected client id when hosted apart from the server', async () => { + const getOAuthClientId = await loadWithMeta( + '', + ); + expect(getOAuthClientId()).toBe('custom'); + }); + it('reads the document only once', async () => { const getOAuthClientId = await loadWithMeta(''); expect(getOAuthClientId()).toBe('pocket-id-client'); diff --git a/src/lib/oauthClientId.ts b/src/lib/oauthClientId.ts index ec125be..efe2144 100644 --- a/src/lib/oauthClientId.ts +++ b/src/lib/oauthClientId.ts @@ -4,14 +4,27 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ -const DEFAULT_CLIENT_ID = 'stalwart-webui'; +// INBUXA requires OAuth clients to be registered, and registers these two on +// every start (inbuxa-server contract C-6). Served by the server itself, this +// is the web interface at /admin, registered as `stalwart-webui`. Hosted +// anywhere else, with the server's address in , it +// is INBUXA Admin, registered as `inbuxa-admin` from INBUXA_ADMIN_URL. +const SERVED_BY_SERVER_CLIENT_ID = 'stalwart-webui'; +const HOSTED_ELSEWHERE_CLIENT_ID = 'inbuxa-admin'; let cached: string | undefined; +function metaContent(name: string): string | undefined { + return document.querySelector(`meta[name="${name}"]`)?.getAttribute('content')?.trim() || undefined; +} + export function getOAuthClientId(): string { if (cached !== undefined) return cached; - const injected = document.querySelector('meta[name="oauth-client-id"]')?.getAttribute('content')?.trim(); - cached = injected ? injected : DEFAULT_CLIENT_ID; + const hostedElsewhere = Boolean( + (import.meta.env.VITE_API_BASE_URL as string | undefined) || metaContent('api-base-url'), + ); + cached = + metaContent('oauth-client-id') ?? (hostedElsewhere ? HOSTED_ELSEWHERE_CLIENT_ID : SERVED_BY_SERVER_CLIENT_ID); return cached; }