add a switch that turns origin checking off entirely
The /api/music exemption was not enough on its own: an app has to reach /api/auth to sign in before it ever calls its own feature, so the login was still 403ing on Invalid origin. ALLOW_ANY_ORIGIN=true now accepts every Origin everywhere and skips the per-origin path scoping. Set on this host; ALLOW_ANY_ORIGIN_MUSIC stays as the narrower option. The account backstop is deliberately NOT disabled — a valid non-owner token is still confined to /api/auth + /api/music whatever Origin it claims, because that rule is account-based rather than origin-based, and it is the airtight half of the pair. Every protected route still requires a valid token. Reverting is an env edit and a restart. Both flags and their call sites come out when the tailnet becomes the perimeter. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -85,18 +85,29 @@ for (const { slug, origin } of APP_ORIGIN_LIST) {
|
||||
// Last, so the web origin wins if an app ever declares the same one.
|
||||
if (PUBLIC_ORIGIN) ORIGIN_RULES[PUBLIC_ORIGIN] = { superAdminOnly: true };
|
||||
|
||||
// ── TEMPORARY: origin exemption for /api/music ──
|
||||
// Off unless ALLOW_ANY_ORIGIN_MUSIC=true. While the platform is still internet-exposed, this lets a music
|
||||
// client that cannot present the app's custom-scheme origin reach /api/music anyway. It drops ONE layer:
|
||||
// a valid token is still required (userMiddleware) and the non-owner account backstop still confines
|
||||
// music accounts. Origin was never authentication — it is client-chosen and trivially forged outside a
|
||||
// browser — so this removes defence in depth, not the lock. Delete once the tailnet is the perimeter.
|
||||
// ── TEMPORARY: origin checking switched off ──
|
||||
// ALLOW_ANY_ORIGIN=true accepts every Origin, everywhere, and skips the per-origin path scoping.
|
||||
// ALLOW_ANY_ORIGIN_MUSIC=true is the narrower version, /api/music only — which is not enough on its own,
|
||||
// because an app has to reach /api/auth to sign in before it ever calls its own feature.
|
||||
//
|
||||
// What still holds with these on: every protected route requires a valid token (userMiddleware), and the
|
||||
// account backstop below still confines a non-owner account to /api/auth + /api/music whatever Origin it
|
||||
// claims — that one is deliberately NOT disabled, since it is account-based, not origin-based.
|
||||
//
|
||||
// What is lost: defence in depth, not the lock. Origin was never authentication here — `officer://<hex>`
|
||||
// is chosen by the client, forgeable outside a browser, and extractable from a shipped app binary.
|
||||
// Both flags and their call sites come out once the tailnet is the perimeter.
|
||||
const ALLOW_ANY_ORIGIN = process.env.ALLOW_ANY_ORIGIN === 'true';
|
||||
const ALLOW_ANY_ORIGIN_MUSIC = process.env.ALLOW_ANY_ORIGIN_MUSIC === 'true';
|
||||
|
||||
export function isMusicOriginExempt(path: string): boolean {
|
||||
return ALLOW_ANY_ORIGIN_MUSIC && pathAllowed(path, ['/api/music']);
|
||||
export function isOriginCheckDisabled(path?: string): boolean {
|
||||
if (ALLOW_ANY_ORIGIN) return true;
|
||||
return ALLOW_ANY_ORIGIN_MUSIC && !!path && pathAllowed(path, ['/api/music']);
|
||||
}
|
||||
|
||||
/** @deprecated use isOriginCheckDisabled — kept so existing call sites read the same. */
|
||||
export const isMusicOriginExempt = isOriginCheckDisabled;
|
||||
|
||||
// True when an Origin is reserved for the platform owner (used at signin to reject a non-owner login).
|
||||
export function isSuperAdminOnlyOrigin(origin: string | undefined): boolean {
|
||||
return !!origin && ORIGIN_RULES[origin]?.superAdminOnly === true;
|
||||
@@ -104,6 +115,7 @@ export function isSuperAdminOnlyOrigin(origin: string | undefined): boolean {
|
||||
|
||||
export function isOriginAllowed(origin: string | undefined, host?: string): boolean {
|
||||
if (IS_DEV_BUILD) return true;
|
||||
if (ALLOW_ANY_ORIGIN) return true;
|
||||
|
||||
if (origin) {
|
||||
if (origin.startsWith('chrome-extension://')) {
|
||||
@@ -178,7 +190,10 @@ export const originScopeMiddleware: MiddlewareHandler = async function (ctx, nex
|
||||
throw errors.FORBIDDEN('This account is limited to the music app');
|
||||
}
|
||||
|
||||
// 2. Per-origin rules.
|
||||
// 2. Per-origin rules. Skipped entirely while origin checking is off (the account backstop above is
|
||||
// account-based, not origin-based, so it deliberately still applies).
|
||||
if (isOriginCheckDisabled(path)) return next();
|
||||
|
||||
const rule = origin ? ORIGIN_RULES[origin] : undefined;
|
||||
if (rule) {
|
||||
if (rule.paths && !pathAllowed(path, rule.paths)) {
|
||||
|
||||
Reference in New Issue
Block a user