feat/ update-user-contact#36
Merged
Merged
Conversation
… persistence, add unique email constraint OTP Ownership & Security: - Add UserId to OtpVerification entity (nullable, for anonymous registration flows) - Pass recipientUserId through ContactChangeOtpService into OTP create/refresh - Add user-scoped FindActiveAsync overload in OtpVerificationRepository to prevent contact-level collisions - Add OTP ownership validation in ConfirmEmailChange and ConfirmPhoneChange handlers - Use entity.UserId in VerifyOtpCommandHandler with fallback to contact lookup for anonymous flows Email/Phone Change Fixes: - Use UserManager.SetEmailAsync + SetUserNameAsync in ConfirmEmailChange instead of raw property mutation (fixes stale NormalizedEmail) - Use UserManager for phone change confirmation with ownership validation Duplicate Account Prevention: - Add filtered unique index on NormalizedEmail to prevent duplicate accounts at DB level - Create EF migration: AddOtpVerificationUserId (adds user_id column + composite index + unique email index)
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.
Summary
DevAuthHandlerwas unconditionally overriding real JWT tokens with the dev-mode cookie, causing all authenticated requests to resolve to the deterministic dev user account. NowDevAuthHandlerprioritizes real JWT validation (from/api/auth/login) and only falls back to dev-mode cookie when no valid JWT is present.OtpVerificationwas not storingUserId, so contact-change confirmations could not verify the OTP belonged to the authenticated user. Added nullableUserIdtoOtpVerification, scopedFindActiveAsyncby user, and added ownership checks in bothConfirmEmailChangeandConfirmPhoneChangehandlers.ConfirmEmailChangewas mutatingEmail/UserName/NormalizedEmaildirectly, leaving the oldNormalizedEmailin the database. Now usesUserManager.SetEmailAsyncandUserManager.SetUserNameAsyncto ensure Identity-managed fields stay consistent.EMAIL_CHANGE_OTP(Email channel) andPHONE_CHANGE_OTP(Sms channel) toReferenceDataSeedersoRequestEmailChangeCommandHandlerandRequestPhoneChangeCommandHandlercan resolve their dedicated templates correctly.NormalizedEmailto prevent duplicate accounts at the database level. AddedUserIdcomposite index onotp_verificationsto support scoped OTP lookups.Test plan
/api/auth/login— JWTsubclaim must match realUser.Id/api/me— must return real account, NOT dev account (aaaaaaaa-aaaa-aaaa-aaaa-000000000005)/api/me/email/request-change) → OTP sent viaEMAIL_CHANGE_OTPtemplate/api/me/email/confirm-change) →/api/meshould show new email/api/me/phone/request-change) → OTP sent viaPHONE_CHANGE_OTPtemplate/api/me/phone/confirm-change) → phone updated on real accountSecurity checklist
otp.UserId == request.UserId[Audited]onUserentity andOtpVerificationBRD traceability
n/a
Screenshots / output (optional)
Build output:
Build succeeded.
0 Warning(s)
0 Error(s)