Repository navigation
Tech-debt batch 14: auth — OAuth email proof, verified invites, effective-permission admin guards (#622 #623 #624) - #647
Merged
Merged
Conversation
…s email-verification proof (#622) OIDC requires email_verified=true, Google the People API metadata.verified of the primary email, GitHub a verified entry in /user/emails; Microsoft (Entra) email claims are never proof. Existing subject links keep working. Claude-Session: https://claude.ai/code/session_01M9neheZZEe3sVpDi2S3zT4
…ter verified OAuth login (#622) Claude-Session: https://claude.ai/code/session_01M9neheZZEe3sVpDi2S3zT4
…h from the user directory (#623) Adds DirectoryUser.email_verified (None = provider doesn't track it); the users directory fills it from is_verified, Keycloak principals carry the token's email_verified claim as the fallback. Claude-Session: https://claude.ai/code/session_01M9neheZZEe3sVpDi2S3zT4
…thority; keep a last admin (#624) A delegate with users.manage grants only roles it holds and cannot manage admins, superusers or stronger accounts; an admin's scoped token manages ordinary accounts but never grants admin. Nobody disables or demotes themselves or the last active admin (serialized with FOR UPDATE on Postgres). Claude-Session: https://claude.ai/code/session_01M9neheZZEe3sVpDi2S3zT4
…ffective permissions Claude-Session: https://claude.ai/code/session_01M9neheZZEe3sVpDi2S3zT4
Deploying simple-module-python with
|
| Latest commit: |
7d474fe
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://41e5b8be.simple-module-python.pages.dev |
| Branch Preview URL: | https://fix-debt-batch-14.simple-module-python.pages.dev |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Tech-debt batch 14 — authentication/authorization fixes from the 2026-10-24 scan.
email_verified: true, Google People APImetadata.verifiedon the primary email, a verified GitHub address from/user/emails; Microsoft (Entra) email claims never count ("nOAuth"). An unverified account — SSO-provisioned ones included, pending invites excepted — never absorbs a later OAuth login (closes a pre-hijacking path raised in review).DirectoryUser.email_verified,None= provider doesn't track it → Keycloak'semail_verifiedclaim), so verifying after sign-in works without re-signing in. Distinctinvitation_email_unverifiederror (en/de).users.managecan grantadmin; no last-admin guard on disable/demote #624 Delegated admin escalation.users/admin/safety.py: outside a full admin session, a role can be granted and an account managed only when its effective permissions (roles + direct grants, token scopes applied) are within the actor's. Delegates and admins' scoped tokens can't grantadmin, can't touch admin/superuser accounts, can't grant roles mapped to permissions they lack. Nobody disables/demotes themselves or the last active admin (row-locked on Postgres).Behaviour changes (CHANGELOG): providers without email proof can't sign in to an existing account by email alone (
400 OAUTH_USER_ALREADY_EXISTS); withrequire_verificationoff, self-registered accounts must verify before accepting an invite.Verification
users.managecan grantadmin; no last-admin guard on disable/demote #624: 28 of 36 new tests fail on the old service; pre-hijack test fails without the guard).make lint✓ ·make test-py(8 workers) ✓ 6082 passed ·make test-js✓ 770 · Postgres (admin guards, effective permissions, tenants, OAuth) ✓.users.managecan grantadmin; no last-admin guard on disable/demote #624 to effective permissions after an automated security finding; demo PAT test retargeted to an account within the token's scopes) → pass 2 clean → QA: delegatedhelpdeskadmin refused on self-grant/admin edits/stronger grants, self-disable and last-admin guards (UI + API); unverified invitee refused then accepted in the same session once verified; OIDC against a real Keycloak: unverified-email identity refused (no link), verified identity linked to the existing account → round-2 review clean.Follow-ups (P3, filed separately): admin UI toasts drop the server's detail; OIDC refusal renders raw JSON.
Closes #622
Closes #623
Closes #624
https://claude.ai/code/session_01M9neheZZEe3sVpDi2S3zT4