Skip to content

auth.login_path: let a site serve its own login page (#159) - #160

Merged
zumbrunn merged 2 commits into
mainfrom
feat/auth-login-path-159
Nov 12, 2026
Merged

zumbrunn merged 2 commits into
mainfrom
feat/auth-login-path-159

Conversation

@zumbrunn

Copy link
Copy Markdown
Member

Fixes #159

site.yaml: auth.login_path: /join (default /auth/login).

  • Redirects to login go to login_path with ?next=: the page gate, a logged-out visitor opening a gated file (mediaDenialResponse), a failed password login (?error=invalid), and the "Try again" link on the magic-link error page.
  • GET /auth/login redirects to login_path (query kept), so there is one login page. Not redirected when login_path is unset or /auth/login, so no loop.
  • Still mounted under /auth/*: POST /auth/login, OAuth callbacks, magic-link send/verify, logout. The custom page posts to them.
  • Validation: login_path must be a local absolute path: one leading /, plain path characters, no //host, URL, query, fragment or ... Config validation rejects anything else; at runtime an invalid value falls back to /auth/login.
  • No self-loop on a gated site: the page whose route is login_path is treated as roles: public by the inheritance pass, so neither auth.default_roles nor a gated ancestor can gate it. Its own roles: still applies.

How it is wired: gating has no config access, so mountDuneAuth registers the path per origin (setGatingLoginPath, same pattern as setGatingAuthz) and enforceRoles reads it with loginPathForRequest(req).

Not in this PR

  • Docs: a "Login redirect" section on 17.authentication/02.content-gating and a config-reference row for login_path, after the release (dune-docs#30 is held until then).
  • The theme login template and the OAuth buttons are untouched; a custom page links to /auth/{provider} itself.

Testing

8 new tests (tests/auth/login_path_test.ts): path validation, config validation, gate and media redirects including per-origin selection, the default-roles exemption (and the loop it prevents), GET /auth/login redirect with query, no redirect when unset or equal to /auth/login, password failure redirect, magic-link error link. tests/auth, config, content, runtime: 625 pass; deno check and deno lint src clean. Not exercised in a browser.

Based on main after #158.

🤖 Generated with Claude Code

zumbrunn and others added 2 commits November 12, 2026 23:40
Gating redirects, a failed password login and the magic-link error page use
the configured path; GET /auth/login redirects to it with the query kept.
The path is validated as a local absolute path, and the page served there is
exempt from default_roles/inherited gating so a gated site cannot loop.

Fixes #159

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…login pages

Every mounted site registers its login path (the default included) so the
single-entry fallback cannot hand one site another's path. A trailing slash is
normalized for redirects and the default_roles exemption. Translations of the
login page (same folder) are exempt too.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@zumbrunn
zumbrunn merged commit 5c96f45 into main Nov 12, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

auth.login_path: let a site serve its own login page

1 participant