pds.dad/lexidraw

ยท Tangled

1 min read Original article โ†—

The client id was baked in from .env.production, so every build pointed at
https://lexidraw.app/oauth-client-metadata.json. On any other origin
BrowserOAuthClient.load() fetched that cross-origin, and the URL carries no
Access-Control-Allow-Origin (nginx.conf used to add it; timber only sets it
for /.well-known/**), so the fetch failed and sign-in died with "Failed to
fetch". Prod worked only by being same-origin. CORS headers alone wouldn't
have been enough โ€” redirect_uris still named prod.

A client id IS the URL its metadata is served from, and a web client's
redirect URIs must sit on that origin, so the document can't be a checked-in
constant. It's now built per origin from PUBLIC_ORIGIN by a route, while the
browser derives the same URL from window.location.origin: one build works on
any https origin and the fetch is always same-origin. Local dev over plain
http still falls through to the loopback client.

With no PUBLIC_ORIGIN set the route reproduces the old prod document exactly,
so client ids embedded in existing sessions keep resolving; a test pins that.

Also drop the memoized rejection in getOAuthClient() โ€” one failed metadata
fetch used to leave sign-in dead for the rest of the page load.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>