feat(proxy): /login, /logout, auth_mode="optional" (home#118 phase 2) #25

Open
timur wants to merge 2 commits from feat_118_login_logout_optional into development
Owner

Phase 2 of home#118 — the hero_proxy-side primitives that unblock guest-first mode for hero_os.

Summary

  • GET /login?next=<path>[&provider=<name>] — picks an OAuth provider (explicit ?provider= or first enabled), stashes CSRF state + sanitized return-to, redirects to the provider's auth URL.
  • GET /logout?next=<path> — deletes the session row, clears the session cookie, redirects.
  • auth_mode="optional" — forwards X-Hero-User/X-Hero-Context/X-Hero-Claims when a valid session exists, forwards as guest otherwise (no redirect). IP-based identity still applies in the guest branch.
  • ?next= is constrained to same-origin relative paths (open-redirect guard).
  • /login and /logout bypass bearer auth in the middleware — they are browser-initiated.
  • Refactors the existing "oauth" branch to share an apply_oauth_session helper with "optional".

Phase 1 (hero_os guest mode) and Phase 3 (hero_auth as an OIDC provider) will land as separate PRs in their own repos.

Test plan

  • cargo test -p hero_proxy_server — 17 passed (4 new)
  • cargo clippy -p hero_proxy_server --all-targets -- -D warnings — clean
  • Manual: configure a DomainRoute for hero_os with auth_mode="optional", hit it with no session → guest; hit /login → OAuth; callback → redirect to next; hit /logout → cookie cleared.

Closes none (parent issue home#118 stays open until all phases ship).

Phase 2 of [home#118](https://forge.ourworld.tf/lhumina_code/home/issues/118) — the hero_proxy-side primitives that unblock guest-first mode for hero_os. ## Summary - `GET /login?next=<path>[&provider=<name>]` — picks an OAuth provider (explicit `?provider=` or first enabled), stashes CSRF state + sanitized return-to, redirects to the provider's auth URL. - `GET /logout?next=<path>` — deletes the session row, clears the session cookie, redirects. - `auth_mode="optional"` — forwards `X-Hero-User`/`X-Hero-Context`/`X-Hero-Claims` when a valid session exists, forwards as guest otherwise (no redirect). IP-based identity still applies in the guest branch. - `?next=` is constrained to same-origin relative paths (open-redirect guard). - `/login` and `/logout` bypass bearer auth in the middleware — they are browser-initiated. - Refactors the existing `"oauth"` branch to share an `apply_oauth_session` helper with `"optional"`. Phase 1 (hero_os guest mode) and Phase 3 (hero_auth as an OIDC provider) will land as separate PRs in their own repos. ## Test plan - [x] `cargo test -p hero_proxy_server` — 17 passed (4 new) - [x] `cargo clippy -p hero_proxy_server --all-targets -- -D warnings` — clean - [ ] Manual: configure a `DomainRoute` for `hero_os` with `auth_mode="optional"`, hit it with no session → guest; hit `/login` → OAuth; callback → redirect to `next`; hit `/logout` → cookie cleared. Closes none (parent issue home#118 stays open until all phases ship).
feat(proxy): add /login, /logout, and auth_mode="optional" (home#118 phase 2)
All checks were successful
Build & Test / check (push) Successful in 2m34s
Build & Test / check (pull_request) Successful in 2m31s
6c7ecbb25b
Introduces the edge-auth primitives hero_proxy needs to front hero_os in
guest-first mode (home#118).

- GET /login?next=<path>[&provider=<name>]: picks an OAuth provider
  (explicit ?provider or first enabled), stashes CSRF state with the
  validated return-to, and redirects to the provider's auth URL. The
  existing /oauth/callback already handles the rest.
- GET /logout?next=<path>: deletes the session row and issues a
  clearing Set-Cookie, then redirects. No provider-side revocation.
- auth_mode="optional": forwards identity headers when a valid session
  exists, forwards as guest (x-proxy-auth-method: none, no X-Hero-*)
  otherwise — no redirect. IP-based identity still applies in the guest
  branch so auto-accept networks keep working.

Open-redirect safety: ?next= is constrained to same-origin relative
paths (rejects //host, /\host, absolute URLs).

Bypass bearer auth for /login and /logout in the middleware since they
are browser-initiated.

Refactors the existing "oauth" branch to share an apply_oauth_session
helper with "optional" so the allowed_emails check and header-injection
policy stay in one place.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
feat(proxy-ui): expose auth_mode="optional" and "signature" in the route editor
All checks were successful
Build & Test / check (pull_request) Successful in 2m47s
Build & Test / check (push) Successful in 2m48s
565cc1fc7b
The dropdown was missing these two values, so they could only be set via
the raw RPC. Also extends the OAuth-provider-select visibility to the
"optional" mode since it honors allowed_emails the same way as "oauth"
when a session is present.

Updated the inline docs table to list the new enum value.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
All checks were successful
Build & Test / check (pull_request) Successful in 2m47s
Build & Test / check (push) Successful in 2m48s
This pull request can be merged automatically.
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin feat_118_login_logout_optional:feat_118_login_logout_optional
git switch feat_118_login_logout_optional

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git switch development
git merge --no-ff feat_118_login_logout_optional
git switch feat_118_login_logout_optional
git rebase development
git switch development
git merge --ff-only feat_118_login_logout_optional
git switch feat_118_login_logout_optional
git rebase development
git switch development
git merge --no-ff feat_118_login_logout_optional
git switch development
git merge --squash feat_118_login_logout_optional
git switch development
git merge --ff-only feat_118_login_logout_optional
git switch development
git merge feat_118_login_logout_optional
git push origin development
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lhumina_code/hero_proxy!25
No description provided.