feat(auth): phone+PIN primary + Google/Apple sign-in, email-OTP signup (W8) - #7
Merged
Merged
Conversation
…p (W8) Make phone the primary credential and add social sign-in, so clients offer three options: phone+PIN, Google, Apple. - Signup proves the person with an EMAILED code (EmailVerification + email_service), not SMS — there is still no SMS provider — so the phone is stored canonical-but-unproven: phone_verified_at stays NULL and no verified phone identity is written. Proving the mailbox is not proving the handset. - registerWithPhone: validate (number/PIN/uniqueness) BEFORE spending the single-use code, so a weak PIN or duplicate does not burn it (reset_pin rule). - signInWithPhonePin: generic, timing-equalised, rate-limited per IP + number. - setMyPhone: the phone a Google/Apple signup collects, UNVERIFIED and no PIN (distinct from linkPhone, which spends an OTP and marks the number proven). - signInWithGoogle / signInWithApple: verify the provider's RS256 ID token in accounts/social.py (PyJWT PyJWKClient; audience pinned to configured client IDs — the anti-forgery control), then reuse identity.sign_in_with_identity (email is never used to match an account). No new dependency beyond cryptography, which PyJWT needs for RS256. - authCapabilities: phoneSignIn is now phone+PIN (always true, no SMS); google/apple are true only when client IDs are configured. +26 tests (accounts/test_w8_auth.py); full suite 404 green under CI config. W7 capability tests updated for the redefined phoneSignIn semantics. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
Makes phone the primary credential and adds social sign-in, so clients offer three options: phone+PIN, Google, Apple.
What's in it
EmailVerification+email_service) — no SMS provider, so the phone is stored canonical-but-unproven (phone_verified_atstays NULL, no verified phone identity). Proving the mailbox ≠ proving the handset.registerWithPhonevalidates number/PIN/uniqueness before spending the single-use code (reset_pin rule).signInWithPhonePin— generic, timing-equalised, rate-limited per IP + number.setMyPhone— the phone a Google/Apple signup collects (unverified, no PIN; distinct from OTP-backedlinkPhone).signInWithGoogle/signInWithApple— verify the provider's RS256 ID token (accounts/social.py, PyJWT JWKS, audience pinned to configured client IDs), then reuse the anti-takeoversign_in_with_identity. No new dep beyondcryptography.authCapabilities:phoneSignInnow = phone+PIN (always true); Google/Apple true only when client IDs are configured.Tests / gates
SMS_BACKEND=disabled); +26 new (accounts/test_w8_auth.py). Ruff clean, no migration drift, authorization-policy test green.Ops before enabling
support@zazatechnologies.com(OTP delivery);GOOGLE_OAUTH_CLIENT_IDS/APPLE_CLIENT_IDSto switch social on.🤖 Generated with Claude Code