Feature 03 task 3: Household group gate and auth middleware #21

Member

Implements Feature 03 task 3 (1f240a09). Done-condition: the callback refuses a session unless the ID token or userinfo groups claim contains a group in MEALQUEST_OIDC_ALLOWED_GROUPS, showing an HTML 403 ("This kitchen is for the household only" + sign out); RequireSession protects /api/v1/* and /media/* (JSON 401 {"error":{"code":"unauthenticated"}}) while /health, /auth/* and static assets stay public; a removed user is refused at next login; tests cover member, non-member, missing groups claim, API 401 without a cookie and /health without a cookie; quality floor passes.

Evidence (developer-run): gofmt empty; go vet clean; go test -race all packages pass; CGO_ENABLED=0 build ok; make test/build ok; live run showed 401 JSON for /api/v1 and /media without a cookie, 200 /health, 302 /auth/login. Adds the canonical actor-in-context helper.

Implements Feature 03 task 3 (1f240a09). Done-condition: the callback refuses a session unless the ID token or userinfo groups claim contains a group in MEALQUEST_OIDC_ALLOWED_GROUPS, showing an HTML 403 ("This kitchen is for the household only" + sign out); RequireSession protects /api/v1/* and /media/* (JSON 401 {"error":{"code":"unauthenticated"}}) while /health, /auth/* and static assets stay public; a removed user is refused at next login; tests cover member, non-member, missing groups claim, API 401 without a cookie and /health without a cookie; quality floor passes. Evidence (developer-run): gofmt empty; go vet clean; go test -race all packages pass; CGO_ENABLED=0 build ok; make test/build ok; live run showed 401 JSON for /api/v1 and /media without a cookie, 200 /health, 302 /auth/login. Adds the canonical actor-in-context helper.
dev_agent added 2 commits 2026-10-03 10:26:41 -04:00
The callback now starts a session only when the verified groups claim
contains a group from MEALQUEST_OIDC_ALLOWED_GROUPS. When the ID token has
no groups claim, groups come from the userinfo endpoint, whose subject must
match the ID token. A refused sign-in gets a 403 HTML page ("This kitchen is
for the household only") with a sign-out button, and no session. The check
runs on every login, so an account removed from the group is refused at its
next one. auth.New requires at least one allowed group and a discovered
userinfo endpoint that passes the endpoint rule.

The RequireSession middleware wraps the /api/v1 and /media subrouters: no
live session gets 401 {"error":{"code":"unauthenticated",...}}, a lookup
failure 500, and a live session reaches the handler with the actor in the
context. It wraps the subrouters instead of using chi's Use because chi
skips middleware on a subrouter with no routes. /health, /auth and the web
build stay public.

auth.WithActor and auth.ActorFrom are the one way to read the signed-in
household member; handlers record Actor.Subject as updated_by.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
End any existing session when a sign-in is refused
CI / ci (pull_request) Successful in 1m24s
Independent review Codex gpt-6-sol high: APPROVED (0 findings)
CI / ci (push) Successful in 1m28s
c824942484
A browser that still holds a session and signs in as an account outside
the household's group got the 403 page but kept its old session. The
refusal now ends that session and clears its cookie first.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
review_agent left a comment
Member

Independent review — Codex gpt-6-sol, reasoning high

Verdict: APPROVED
Reviewed SHA: c824942484eceb492a88a382c8455a5f2f84aad3

{
  "verdict": "APPROVED",
  "reviewed_sha": "c824942484eceb492a88a382c8455a5f2f84aad3",
  "summary": "The group gate, refusal page, session middleware, public routes, and actor context meet the stated done-condition. Tests cover the required cases. gofmt, go vet, and go test -race -count=1 ./... passed.",
  "findings": []
}

Posted unaltered by review_agent. This is transport, not a second review.

## Independent review — Codex `gpt-6-sol`, reasoning high Verdict: **APPROVED** Reviewed SHA: `c824942484eceb492a88a382c8455a5f2f84aad3` ```json { "verdict": "APPROVED", "reviewed_sha": "c824942484eceb492a88a382c8455a5f2f84aad3", "summary": "The group gate, refusal page, session middleware, public routes, and actor context meet the stated done-condition. Tests cover the required cases. gofmt, go vet, and go test -race -count=1 ./... passed.", "findings": [] } ``` --- Posted unaltered by `review_agent`. This is transport, not a second review.
approver_agent merged commit b2201c5da1 into feature/9c4eba48-9a49-4b73-a85f-a4bc19eb4062-authentik-oidc-sessions 2026-10-03 10:30:08 -04:00
Sign in to join this conversation.
No Reviewers
No labels
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Maniacs_Mansion/MealQuest#21