Repository navigation
Add Apple and Google sign-in with optional two-factor authentication - #277
Merged
Merged
Conversation
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.
Existing CMS accounts can now explicitly connect Apple or Google from Profile and optionally require a second factor after password or provider sign-in. React uses the same allauth browser-session flow for initial sign-in and expired sessions; an email match alone never links accounts or grants workspace access.
Changes
This branch excludes the separate diagnostics work in #275.
Local verification
cd backend && python manage.py test cms_auth --settings=cms_auth.test_settings --noinput— 36 passed. Includes real software WebAuthn registration/assertion, mocked Apple/Google callback boundaries, recovery-code reuse/replacement, encrypted storage, credential revocation, tenant membership preservation, actual ASGI sessions and the real Kanban consumer.python manage.py makemigrations cms_auth --check --dry-run --settings=cms_auth.test_settings— no changes.cd frontend && npx vitest run src/components/auth/__tests__/AuthenticationForm.test.jsx src/components/auth/__tests__/AccountSecurityPanel.test.jsx src/api/__tests__/auth.test.js src/api/__tests__/client.test.js src/contexts/__tests__/AuthContext.test.jsx src/pages/__tests__/LoginPage.inbox.test.jsx src/pages/__tests__/ProfilePage.test.jsx— 23 passed, including the two limited-role regressions already on main.npm run build— passed; existing chunk-size warnings remain.git diff --check— passed.The normal project test runner passed 35 tests (
core.tests.AdminPasswordResetLinkTest cms_auth) using full project migrations on isolated PostgreSQL 17 with development auto-login disabled. The current standalone auth suite passes 36 tests. Broader unrelated suites were not repeated. Live provider acceptance needs ECEEE-owned credentials and a registered HTTPS test origin; PostgreSQL concurrency and the target's allauth upgrade history remain unverified.Review fixes
Prevent in-flight security mutations from promoting already-revoked browser sessions to the new security version. Serialize the final login version check and session stamp with credential revocation under the same user-row lock. Regression tests cover stale/current sessions and obsolete pending login state.
Show rejected provider connections directly in Profile rather than initializing the message inside an unmounted reauthentication form. Tests cover both callback reasons and an ordinary Profile visit.
Correct operator-generated reset URLs to use allauth's user-ID format and return the serialized URL. Real API regressions cover redemption, one-time use, MFA preservation and credential revocation.
Make auth tests preserve the migration-created user set rather than assuming an empty database.
Keep expired-session authentication on the current page with password and MFA. Provider redirects remain on the login page; the dialog omits them to preserve unsaved editor work and queued requests.
Update browser login regressions and their mock to the allauth session/CSRF contract; verify that personal JWTs are not stored. Both targeted Playwright tests and fixture/spec lint passed locally.
CI status
Publisher's undici is updated from 7.30.0 to the patched 7.30.1 within the existing dependency range. Local verification passed: clean npm ci, npm audit --omit=dev --audit-level=high (zero vulnerabilities), 97 Publisher tests (two PostgreSQL-only tests skipped locally), lint, typecheck and production build/client-bundle verification. Previous head
8f58f15654632c37b0f546402a7450dcf43db7dcpassed Fast CI and Full CI (40089125397). Review-fix head59091e26passes 36 isolated auth backend tests, 23 focused frontend tests, frontend build, changed-file Python/JS lint andgit diff --check; Fast CI and Full CI, including both gate checks, succeeded for exact head59091e26199635050d00293b52f1bc4af85930ea. The initial Fast CI import-options test failure did not reproduce in its isolated local test, a complete local frontend run (1,927 passing tests) or either remote rerun; no code was changed to obtain the rerun. PostgreSQL concurrency, live provider acceptance and browser visual checks were not repeated for these fixes. No merge or deployment has been performed.Risk and rollout
This is an authentication/authorization change and requires security review. The application migration only creates the account revocation-state table; it does not backfill accounts, change memberships or manufacture email verification. Normal allauth migrations must also be reviewed against the target installation.
Provider configuration, MFA encryption-key provisioning and actual HTTPS acceptance are required before enabling the feature. No public signup, passwordless login, trusted-browser bypass or operator MFA recovery is added. After MFA enrollment, reverting to older code that ignores MFA would be unsafe; preserve data/keys and prefer a reviewed roll-forward.
This coherent authentication change is worth a full CI run. Full CI and fresh owner sign-off are required before merging; CI is not code-review approval. No merge or production deployment is authorized or performed.
Current-head merge risk review
Independent P0–P3 review is clean at
59091e26199635050d00293b52f1bc4af85930ea; no verified unresolved or ignored findings. GitHub has no submitted reviews, no review decision and no unresolved inline review threads; CI is separate evidence. Head is mergeable/CLEAN.The CMS migration creates only a user-bound state table, with lazy rows and no user/email/membership backfill. Standard Django transactional migration tracking governs installation, upgrade and retry; there is no resumable data backfill. Per-user locks serialize revocation/login state changes. Full CI passed PostgreSQL integration/migration checks. The target's existing migration history, true PostgreSQL concurrency and real HTTPS provider acceptance remain unverified and must be addressed before rollout. Preserve MFA keys and security state, and prefer roll-forward; reverting to pre-MFA code after enrollment can bypass protection. No production mutation, data reset or restoration is included. Fresh explicit owner sign-off acknowledging these authentication/authorization and migration risks is still required to merge this exact head.