AUTH4D-112 branded error and landing pages on the auth origin

Browsers that reach a bad link on the auth origin get a hosted-login screen with the right HTTP status instead of JSON or the plain text Not found. API and fetch callers get exactly the responses they got before.

Which requests get a page

A request is a browser navigation only when it is a GET and either sends Sec-Fetch-Mode: navigate or has an Accept header containing text/html. POST, HEAD and fetch calls with Accept: application/json are never navigations.

Request (navigation) Status Screen
GET /oauth/authorize error that cannot redirect 400 This sign-in link is not valid
GET /oauth/authorize when sign-in is unavailable 503 Sign-in is temporarily unavailable
GET /oauth/logout (logout is a JSON POST) 400 This sign-out link is not valid
Any other path with no route, including /login/<x> 404 Page not found

Authorize errors that cannot redirect are an unknown or disabled client or tenant, an unregistered redirect_uri, a missing or invalid state, and unknown or repeated parameters. The status of the JSON error is kept. Errors that redirect to the client (invalid_scope, unauthorized_client, malformed PKCE) and the normal 302 to /login are unchanged.

Never changed, whatever the headers: management paths (401 JSON without a bearer token), token, revocation, UserInfo, discovery and JWKS responses, every POST, and JSON clients on authentication paths, which still get {"error":"invalid_request"} with 404 for an unknown path.

Response

GET {AUTH_ORIGIN}/oauth/authorize?tenant_id=ten_...&client_id=cli_unknown...
Accept: text/html

HTTP/1.1 400 Bad Request
Content-Type: text/html; charset=utf-8
Cache-Control: no-store, max-age=0

The body is the hosted-login shell (/login/error, built from apps/login) with one extra tag in <head>: <meta name="auth4-error" content="<code>" />. The code is one of invalid_link, invalid_logout_link, not_found or temporarily_unavailable, chosen by the API from a fixed list. The screen shows fixed copy for that code; no server-provided description is rendered. The page keeps the strict hosted-login CSP. If the hosted-login build cannot be read, the API answers with a short plain-text message and the same status.

GET {AUTH_ORIGIN}/login/error?error=<code> shows the same screen directly. Unknown codes show a generic “Something went wrong” screen.

Landing page

GET {AUTH_ORIGIN}/ shows a card with the auth4.dev logo, a short description of the sign-in service and links to the public site and the developer console. On auth.<domain> the links go to https://<domain> and https://app.<domain>; elsewhere (local development) they go to production.

Tests

  • tests/integration/auth4d-112.browser-error-pages.test.ts: HTML and JSON variants for authorize (unknown client, unregistered redirect URI, missing tenant), logout and unknown paths, plus the management, discovery and JWKS paths that never change.

Source: docs/api-spec/auth4d-112.md