Repository navigation
OpenConceptLab/ocl_online#482 | SSO sign-in matches a legacy mixed-case username on its verified email - #958
Conversation
…se username on its verified email instead of creating a case twin
snyaggarwal
left a comment
There was a problem hiding this comment.
Review: no blocking findings.
I found no actionable correctness or security issues in the SSO username matching and refusal-path changes. The case-insensitive fallback is gated by a verified email match, exact username matches remain preferred when applicable, ambiguous case-only matches are refused, and the refusal base class is propagated through the middleware with coverage for the new 401 path.
Verification:
- PR checks run 99: successful.
git diff --check: passed.- Python syntax compilation for all changed files: passed.
- The available API container was on an older commit and could not run the PR’s targeted test classes.
GitHub does not allow the PR author to approve their own pull request, so this was posted as a comment review.
Codex review, pass 1 (codex-cli 0.164.0, commit 386b49f)Verdict: clean. No findings on Locally, findings.json{
"reviewer": "codex-cli 0.164.0",
"perspective": "defects",
"mode": "full",
"commit": "386b49f5",
"verdict": "clean",
"prior": [],
"findings": []
} |
paynejd
left a comment
There was a problem hiding this comment.
Approved. Codex came back clean (see above), the PR's 50 backend and middleware tests pass locally, and CI's only failure comes from master.
An adversarial security pass found nothing P0 or P1 here. The case-insensitive path needs the verified email, and every sign-in path (browser, bearer token, middleware, GraphQL) refuses cleanly without leaving a token behind. The notes, and the cleanup steps for the existing twins, are on ocl_online#482. Merge when CI is green on a fresh master.
Fixes OpenConceptLab/ocl_online#482.
Keycloak sends a lowercase
preferred_username, so a legacy mixed-case account (e.g.GDolin) wasn't matched and SSO sign-in created a case twin (gdolin).filter_users_by_claimsnow matches, after thesuband exact-username lookups, an account whose username equals the claim ignoring case, but only when the claims carry that account's verified email (the rule deactivated accounts already use). Otherwise the sign-in is refused with a newSSOUsernameCaseMismatchRefused(401) and logged; no account is created. Several case-only matches are refused too, and an account linked to another Keycloak user still raisesSSOIdentityMismatchRefused.The three refusal exceptions now share a
SSOSignInRefusedbase, caught by the backend and the auth middleware.Existing case twins are left as they are; the exact (lowercase) username still wins over a case variant.
Tests: case-insensitive match on verified email, refusal for each bad email claim, multiple case-only matches, sub mismatch, reactivation of a deactivated mixed-case account, exact match preferred, end-to-end
get_or_create_user, and the middleware's 401.🤖 Generated with Claude Code