Skip to content

fix(auth): enforce the forced password change on the server - #217

Open
TartanLeGrand wants to merge 2 commits into
BananaOps:mainfrom
TartanLeGrand:fix/auth-enforce-password-change
Open

TartanLeGrand wants to merge 2 commits into
BananaOps:mainfrom
TartanLeGrand:fix/auth-enforce-password-change

Conversation

@TartanLeGrand

Copy link
Copy Markdown
Contributor

What

A user flagged mustChangePassword (the bootstrap admin, users created or reset by an administrator) could call every API endpoint with their session: only the web UI redirected them to the password page. The server now enforces it.

  • Principal carries MustChangePassword, set from the user record when a session is resolved. API keys, anonymous callers and OpenID Connect users are never flagged.
  • authz.CheckPermission refuses a flagged principal for every permission except public ones: HTTP 403 {"error":"password change required"}, gRPC PermissionDenied. It covers every RPC (through Authorize) and every hand-written route wrapped by RequireHTTP (links, Homer).
  • Still reachable while flagged: GET /auth/me, GET /auth/config, login, logout and POST /auth/password (not wrapped by authz). Web assets, /config.js and the API docs serve no data and are unchanged.
  • An invalid credential still answers 401 first.
  • Metric: tracker_auth_requests_total{result="password_change_required"}.

Behaviour around the change

  • Changing the password clears the flag, bumps the session version and issues a new cookie; the old cookie answers 401. The web change-password page (feat(web): login page, auth context and admin pages #201) already uses the response cookie, so its flow is unchanged.
  • An administrator reset signs the user's existing sessions out (session version bump); the restriction applies from their next login.

Checks

  • go test (serial, MongoDB 7): green. New tests: authz unit tests, resolver test, an end-to-end flow through the real mux (flagged admin gets 403 on data and admin endpoints, 200 on /auth/me, changes the password, new cookie works, old cookie 401, logout works while flagged), team API keys unaffected by their creator's flag.
  • Mutation check: with the rule disabled, four tests fail.
  • go vet, golangci-lint (0 issues), gosec (0 issues).

Existing service tests that called admin RPCs as the (flagged) bootstrap admin now clear the flag on their test principal only; production behaviour is not relaxed.

Refs #196

A user flagged mustChangePassword (bootstrap admin, users created or
reset by an administrator) could call every RPC and protected route with
their session: only the web UI redirected them to the password page.

The flag is now carried by the principal and CheckPermission refuses
every non-public permission with 403 "password change required". Public
RPCs (Me, GetAuthConfig) and the unguarded login, logout and
change-password handlers stay reachable. API keys, anonymous and OIDC
principals never carry the flag. The refusal is counted as
result="password_change_required" in tracker_auth_requests_total.

Refs BananaOps#196
Document the password_change_required metric result, state precisely
which calls stay reachable and what an administrator reset does to
existing sessions, and assert the refused RPC code and message.

Refs BananaOps#196

This branch has not been deployed

No deployments
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.

1 participant