feat(identity): add single-use Email/Phone 2FA token providers#25316
Merged
feat(identity): add single-use Email/Phone 2FA token providers#25316
Conversation
Replaces the TOTP-based Email/Phone 2FA providers under TokenOptions.DefaultEmailProvider / DefaultPhoneProvider with DataProtector-backed single-use equivalents. - Encrypt the 6-digit code via IDataProtector (purpose chain isolated per provider + token purpose), store ciphertext + absolute UTC expiration (unix seconds) in the user token table - Remove the stored entry on successful validation (true single-use) - Concurrency race (ConcurrencyStamp failure) returns false instead of 500 - Configurable TokenLifespan (default 3 minutes) via Options AbpSingleActiveTokenProvider.GenerateAsync now checks the IdentityResult from UserManager.UpdateAsync so a silent persistence failure no longer returns a token that was not saved. Related to #25314.
Contributor
There was a problem hiding this comment.
Pull request overview
Introduces ABP-managed Email and Phone two-factor token providers that generate and validate single-use numeric codes backed by Data Protection and persisted in the user token store, replacing the default ASP.NET Core Identity TOTP-based Email/Phone providers.
Changes:
- Added
AbpTwoFactorTokenProviderbase implementation + configurable options (TokenLifespan,CodeLength) for single-use 2FA codes stored in user tokens. - Registered new email/phone 2FA providers under
TokenOptions.DefaultEmailProvider/DefaultPhoneProviderand added comprehensive test coverage. - Hardened
AbpSingleActiveTokenProvider.GenerateAsyncto fail ifUserManager.UpdateAsyncdoesn’t succeed.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpTwoFactorTokenProvider.cs | Core single-use 2FA provider logic: generate, persist, validate, consume, cleanup. |
| modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpTwoFactorTokenProviderOptions.cs | New shared options for code lifespan and length. |
| modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpEmailTwoFactorTokenProvider.cs | Email provider implementation built on the shared base. |
| modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpEmailTwoFactorTokenProviderOptions.cs | Email provider options type for configuration binding. |
| modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpPhoneNumberTwoFactorTokenProvider.cs | Phone provider implementation built on the shared base. |
| modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpPhoneNumberTwoFactorTokenProviderOptions.cs | Phone provider options type for configuration binding. |
| modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpIdentityAspNetCoreModule.cs | Registers the new providers under Identity’s default Email/Phone provider keys. |
| modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpSingleActiveTokenProvider.cs | Ensures persistence failures are not silently ignored when storing token hash. |
| modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/AbpTwoFactorTokenProviderTestBase.cs | Shared behavioral test suite for all ABP 2FA providers (single-use, cleanup, isolation, etc.). |
| modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/AbpEmailTwoFactorTokenProvider_Tests.cs | Email-specific tests (registration, options defaults, stamp change behavior, etc.). |
| modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/AbpPhoneNumberTwoFactorTokenProvider_Tests.cs | Phone-specific tests (registration, confirmed phone requirement, change-phone semantics, etc.). |
EngincanV
approved these changes
Apr 27, 2026
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.
Replaces TOTP-based Email/Phone 2FA providers under
TokenOptions.DefaultEmailProvider/DefaultPhoneProviderwith DataProtector-backed single-use equivalents.IDataProtectorfalseinstead of 500TokenLifespanvia OptionsAbpSingleActiveTokenProvider.GenerateAsyncnow checks theIdentityResultfromUserManager.UpdateAsyncso a silent persistence failure no longer returns a token that was not saved.Because
IdentityOptions.Tokens.ChangePhoneNumberTokenProviderdefaults toTokenOptions.DefaultPhoneProvider,UserManager.GenerateChangePhoneNumberTokenAsync/VerifyChangePhoneNumberTokenAsyncalso inherit the new single-use, stored-token semantics. Phone-change tokens issued before upgrade stop working.Related to #25314.