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.
This branch is out-of-date with the base branch
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.