You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Identity verification endpoints currently have no resend cooldowns or brute-force protection. This was raised on PR #198 by Copilot's automated review and the security argument generalizes to the email flow as well, so we're filing it as a single follow-up rather than landing a phone-only mitigation.
Affected endpoints
Email (already merged):
POST /Identity/Account/Manage/Email — re-sends change-email confirmation link; no cooldown.
POST /Identity/Account/ResendEmailConfirmation — anonymous resend; no cooldown.
POST /Identity/Account/Manage/SendPhoneVerificationCode — generates token, dispatches via ISmsSender. No cooldown. Risk: signed-in user can pump SMS to arbitrary numbers, driving provider costs.
POST /Identity/Account/Manage/ConfirmPhoneNumber — accepts 6-digit code. No failed-attempt tracking. Risk: signed-in attacker (or stolen session) can brute-force ChangePhoneNumberAsync until a code lands.
What we want
Resend cooldown — per-user, per-channel (email or phone), e.g. 60 seconds between sends. Probably backed by IDistributedCache so it works across processes.
Attempt cap on code submission — for both email-confirmation links (less critical, signed token) and phone 6-digit codes (critical, narrow search space). Lock further attempts for N minutes after K failures.
Auditing — emit an AuditLogs event on resend and on failed verification so abuse is visible.
Notes
Token TTL is already short (default 1h for DataProtectionTokenProvider), but that does nothing against a fast brute-forcer of 6 digits.
We have SimpleModule.RateLimiting available — route-level limits would catch the most blatant cases for free, but won't stop a single authenticated session pacing itself under the threshold. The real fix is per-user/per-channel counters.
Summary
Identity verification endpoints currently have no resend cooldowns or brute-force protection. This was raised on PR #198 by Copilot's automated review and the security argument generalizes to the email flow as well, so we're filing it as a single follow-up rather than landing a phone-only mitigation.
Affected endpoints
Email (already merged):
POST /Identity/Account/Manage/Email— re-sends change-email confirmation link; no cooldown.POST /Identity/Account/ResendEmailConfirmation— anonymous resend; no cooldown.Phone (added in #198 / #174):
POST /Identity/Account/Manage/SendPhoneVerificationCode— generates token, dispatches viaISmsSender. No cooldown. Risk: signed-in user can pump SMS to arbitrary numbers, driving provider costs.POST /Identity/Account/Manage/ConfirmPhoneNumber— accepts 6-digit code. No failed-attempt tracking. Risk: signed-in attacker (or stolen session) can brute-forceChangePhoneNumberAsyncuntil a code lands.What we want
IDistributedCacheso it works across processes.AuditLogsevent on resend and on failed verification so abuse is visible.Notes
DataProtectionTokenProvider), but that does nothing against a fast brute-forcer of 6 digits.SimpleModule.RateLimitingavailable — route-level limits would catch the most blatant cases for free, but won't stop a single authenticated session pacing itself under the threshold. The real fix is per-user/per-channel counters.