aspnetcore icon indicating copy to clipboard operation
aspnetcore copied to clipboard

UserManager and SignInManager cancellation tokens

Open TheYoxy opened this issue 2 years ago • 1 comments

Background and Motivation

As is, the class UserManager<TUser>and the class SignInManager<TUser> implements async methods, without the ability to pass a CancellationToken directly in the methods itself.

This proposal follows the issue #45567.

Proposed API

namespace Microsoft.AspNetCore.Identity;

public class UserManager<TUser> : IDisposable where TUser : class
{
-    protected virtual CancellationToken CancellationToken => CancellationToken.None;

-    public virtual Task<IdentityResult> UpdateAsync(TUser user)
+    public virtual Task<IdentityResult> UpdateAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual Task<IdentityResult> DeleteAsync(TUser user)
+    public virtual Task<IdentityResult> DeleteAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual Task<TUser?> FindByIdAsync(string userId)
+    public virtual Task<TUser?> FindByIdAsync(string userId, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<TUser?> FindByNameAsync(string userName)
+    public virtual async Task<TUser?> FindByNameAsync(string userName, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<IdentityResult> CreateAsync(TUser user, string password)
+    public virtual async Task<IdentityResult> CreateAsync(TUser user, string password, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task UpdateNormalizedUserNameAsync(TUser user)
+    public virtual async Task UpdateNormalizedUserNameAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<string?> GetUserNameAsync(TUser user)
+    public virtual async Task<string?> GetUserNameAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<IdentityResult> SetUserNameAsync(TUser user, string? userName)
+    public virtual async Task<IdentityResult> SetUserNameAsync(TUser user, string? userName, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<string> GetUserIdAsync(TUser user)
+    public virtual async Task<string> GetUserIdAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<bool> CheckPasswordAsync(TUser user, string password)
+    public virtual async Task<bool> CheckPasswordAsync(TUser user, string password, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual Task<bool> HasPasswordAsync(TUser user)
+    public virtual Task<bool> HasPasswordAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<IdentityResult> AddPasswordAsync(TUser user, string password)
+    public virtual async Task<IdentityResult> AddPasswordAsync(TUser user, string password, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<IdentityResult> ChangePasswordAsync(TUser user, string currentPassword, string newPassword)
+    public virtual async Task<IdentityResult> ChangePasswordAsync(TUser user, string currentPassword, string newPassword, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<IdentityResult> RemovePasswordAsync(TUser user)
+    public virtual async Task<IdentityResult> RemovePasswordAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))

-    protected virtual async Task<PasswordVerificationResult> VerifyPasswordAsync(IUserPasswordStore<TUser> store, TUser user, string password)
+    protected virtual async Task<PasswordVerificationResult> VerifyPasswordAsync(IUserPasswordStore<TUser> store, TUser user, string password, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<string> GetSecurityStampAsync(TUser user)
+    public virtual async Task<string> GetSecurityStampAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<IdentityResult> UpdateSecurityStampAsync(TUser user)
+    public virtual async Task<IdentityResult> UpdateSecurityStampAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual Task<string> GeneratePasswordResetTokenAsync(TUser user)
+    public virtual Task<string> GeneratePasswordResetTokenAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<IdentityResult> ResetPasswordAsync(TUser user, string token, string newPassword)
+    public virtual async Task<IdentityResult> ResetPasswordAsync(TUser user, string token, string newPassword, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual Task<TUser?> FindByLoginAsync(stringloginProvider, string providerKey)
+    public virtual Task<TUser?> FindByLoginAsync(stringloginProvider, string providerKey, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<IdentityResult> RemoveLoginAsync(TUser user, string loginProvider, string providerKey)
+    public virtual async Task<IdentityResult> RemoveLoginAsync(TUser user, string loginProvider, string providerKey, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<IdentityResult> AddLoginAsync(TUser user, UserLoginInfo login)
+    public virtual async Task<IdentityResult> AddLoginAsync(TUser user, UserLoginInfo login, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<IList<UserLoginInfo>> GetLoginsAsync(TUser user)
+    public virtual async Task<IList<UserLoginInfo>> GetLoginsAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual Task<IdentityResult> AddClaimAsync(TUser user, Claim claim)
+    public virtual Task<IdentityResult> AddClaimAsync(TUser user, Claim claim, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<IdentityResult> AddClaimsAsync(TUser user, IEnumerable<Claim> claims)
+    public virtual async Task<IdentityResult> AddClaimsAsync(TUser user, IEnumerable<Claim> claims, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<IdentityResult> ReplaceClaimAsync(TUser user, Claim claim, Claim newClaim)
+    public virtual async Task<IdentityResult> ReplaceClaimAsync(TUser user, Claim claim, Claim newClaim, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual Task<IdentityResult> RemoveClaimAsync(TUser user, Claim claim)
+    public virtual Task<IdentityResult> RemoveClaimAsync(TUser user, Claim claim, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<IdentityResult> RemoveClaimsAsync(TUser user, IEnumerable<Claim> claims)
+    public virtual async Task<IdentityResult> RemoveClaimsAsync(TUser user, IEnumerable<Claim> claims, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<IList<Claim>> GetClaimsAsync(TUser user)
+    public virtual async Task<IList<Claim>> GetClaimsAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<IdentityResult> AddToRoleAsync(TUser user, string role)
+    public virtual async Task<IdentityResult> AddToRoleAsync(TUser user, string role, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<IdentityResult> AddToRolesAsync(TUser user, IEnumerable<string> roles)
+    public virtual async Task<IdentityResult> AddToRolesAsync(TUser user, IEnumerable<string> roles, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<IdentityResult> RemoveFromRoleAsync(TUser user, string role)
+    public virtual async Task<IdentityResult> RemoveFromRoleAsync(TUser user, string role, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<IdentityResult> RemoveFromRolesAsync(TUser user, IEnumerable<string> roles)
+    public virtual async Task<IdentityResult> RemoveFromRolesAsync(TUser user, IEnumerable<string> roles, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<IList<string>> GetRolesAsync(TUser user)
+    public virtual async Task<IList<string>> GetRolesAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<bool> IsInRoleAsync(TUser user, string role)
+    public virtual async Task<bool> IsInRoleAsync(TUser user, string role, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<string?> GetEmailAsync(TUser user)
+    public virtual async Task<string?> GetEmailAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<IdentityResult> SetEmailAsync(TUser user, string? email)
+    public virtual async Task<IdentityResult> SetEmailAsync(TUser user, string? email, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<TUser?> FindByEmailAsync(string email)
+    public virtual async Task<TUser?> FindByEmailAsync(string email, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task UpdateNormalizedEmailAsync(TUser user)
+    public virtual async Task UpdateNormalizedEmailAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual Task<string> GenerateEmailConfirmationTokenAsync(TUser user)
+    public virtual Task<string> GenerateEmailConfirmationTokenAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<IdentityResult> ConfirmEmailAsync(TUser user, string token)
+    public virtual async Task<IdentityResult> ConfirmEmailAsync(TUser user, string token, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<bool> IsEmailConfirmedAsync(TUser user)
+    public virtual async Task<bool> IsEmailConfirmedAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual Task<string> GenerateChangeEmailTokenAsync(TUser user, string newEmail)
+    public virtual Task<string> GenerateChangeEmailTokenAsync(TUser user, string newEmail, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<IdentityResult> ChangeEmailAsync(TUser user, string newEmail, string token)
+    public virtual async Task<IdentityResult> ChangeEmailAsync(TUser user, string newEmail, string token, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<string?> GetPhoneNumberAsync(TUser user)
+    public virtual async Task<string?> GetPhoneNumberAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<IdentityResult> SetPhoneNumberAsync(TUser user, string? phoneNumber)
+    public virtual async Task<IdentityResult> SetPhoneNumberAsync(TUser user, string? phoneNumber, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<IdentityResult> ChangePhoneNumberAsync(TUser user, string phoneNumber, string token)
+    public virtual async Task<IdentityResult> ChangePhoneNumberAsync(TUser user, string phoneNumber, string token, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual Task<bool> IsPhoneNumberConfirmedAsync(TUser user)
+    public virtual Task<bool> IsPhoneNumberConfirmedAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual Task<string> GenerateChangePhoneNumberTokenAsync(TUser user, string phoneNumber)
+    public virtual Task<string> GenerateChangePhoneNumberTokenAsync(TUser user, string phoneNumber, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual Task<bool> VerifyChangePhoneNumberTokenAsync(TUser user, string token, string phoneNumber)
+    public virtual Task<bool> VerifyChangePhoneNumberTokenAsync(TUser user, string token, string phoneNumber, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<bool> VerifyUserTokenAsync(TUser user, string tokenProvider, string purpose, string token)
+    public virtual async Task<bool> VerifyUserTokenAsync(TUser user, string tokenProvider, string purpose, string token, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual Task<string> GenerateUserTokenAsync(TUser user, string tokenProvider, string purpose)
+    public virtual Task<string> GenerateUserTokenAsync(TUser user, string tokenProvider, string purpose, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<IList<string>> GetValidTwoFactorProvidersAsync(TUser user)
+    public virtual async Task<IList<string>> GetValidTwoFactorProvidersAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<bool> VerifyTwoFactorTokenAsync(TUser user, string tokenProvider, string token)
+    public virtual async Task<bool> VerifyTwoFactorTokenAsync(TUser user, string tokenProvider, string token, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual Task<string> GenerateTwoFactorTokenAsync(TUser user, string tokenProvider)
+    public virtual Task<string> GenerateTwoFactorTokenAsync(TUser user, string tokenProvider, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<bool> GetTwoFactorEnabledAsync(TUser user)
+    public virtual async Task<bool> GetTwoFactorEnabledAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<IdentityResult> SetTwoFactorEnabledAsync(TUser user, bool enabled)
+    public virtual async Task<IdentityResult> SetTwoFactorEnabledAsync(TUser user, bool enabled, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<bool> IsLockedOutAsync(TUser user)
+    public virtual async Task<bool> IsLockedOutAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<IdentityResult> SetLockoutEnabledAsync(TUser user, bool enabled)
+    public virtual async Task<IdentityResult> SetLockoutEnabledAsync(TUser user, bool enabled, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<bool> GetLockoutEnabledAsync(TUser user)
+    public virtual async Task<bool> GetLockoutEnabledAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<DateTimeOffset?> GetLockoutEndDateAsync(TUser user)
+    public virtual async Task<DateTimeOffset?> GetLockoutEndDateAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<IdentityResult> SetLockoutEndDateAsync(TUser user, DateTimeOffset? lockoutEnd)
+    public virtual async Task<IdentityResult> SetLockoutEndDateAsync(TUser user, DateTimeOffset? lockoutEnd, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<IdentityResult> AccessFailedAsync(TUser user)
+    public virtual async Task<IdentityResult> AccessFailedAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<IdentityResult> ResetAccessFailedCountAsync(TUser user)
+    public virtual async Task<IdentityResult> ResetAccessFailedCountAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<int> GetAccessFailedCountAsync(TUser user)
+    public virtual async Task<int> GetAccessFailedCountAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual Task<IList<TUser>> GetUsersForClaimAsync(Claim claim)
+    public virtual Task<IList<TUser>> GetUsersForClaimAsync(Claim claim, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual Task<IList<TUser>> GetUsersInRoleAsync(string roleName)
+    public virtual Task<IList<TUser>> GetUsersInRoleAsync(string roleName, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual Task<string?> GetAuthenticationTokenAsync(TUser user, string loginProvider, string tokenName)
+    public virtual Task<string?> GetAuthenticationTokenAsync(TUser user, string loginProvider, string tokenName, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<IdentityResult> SetAuthenticationTokenAsync(TUser user, string loginProvider, string tokenName, string? tokenValue)
+    public virtual async Task<IdentityResult> SetAuthenticationTokenAsync(TUser user, string loginProvider, string tokenName, string? tokenValue, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<IdentityResult> RemoveAuthenticationTokenAsync(TUser user, string loginProvider, string tokenName)
+    public virtual async Task<IdentityResult> RemoveAuthenticationTokenAsync(TUser user, string loginProvider, string tokenName, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual Task<string?> GetAuthenticatorKeyAsync(TUser user)
+    public virtual Task<string?> GetAuthenticatorKeyAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<IdentityResult> ResetAuthenticatorKeyAsync(TUser user)
+    public virtual async Task<IdentityResult> ResetAuthenticatorKeyAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<IEnumerable<string>?> GenerateNewTwoFactorRecoveryCodesAsync(TUser user, int number)
+    public virtual async Task<IEnumerable<string>?> GenerateNewTwoFactorRecoveryCodesAsync(TUser user, int number, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<IdentityResult> RedeemTwoFactorRecoveryCodeAsync(TUser user, string code)
+    public virtual async Task<IdentityResult> RedeemTwoFactorRecoveryCodeAsync(TUser user, string code, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual Task<int> CountRecoveryCodesAsync(TUser user)
+    public virtual Task<int> CountRecoveryCodesAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<byte[]> CreateSecurityTokenAsync(TUser user)
+    public virtual async Task<byte[]> CreateSecurityTokenAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))

-    private async Task UpdateSecurityStampInternal(TUser user)
+    private async Task UpdateSecurityStampInternal(TUser user, CancellationToken cancellationToken = default(CancellationToken))

-    protected virtual Task<IdentityResult> UpdatePasswordHash(TUser user, string newPassword, bool validatePassword)
+    protected virtual Task<IdentityResult> UpdatePasswordHash(TUser user, string newPassword, bool validatePassword, CancellationToken cancellationToken = default(CancellationToken))

-    private async Task<IdentityResult> UpdatePasswordHash(IUserPasswordStore<TUser> passwordStore, TUser user, string? newPassword, bool validatePassword = true)
+    private async Task<IdentityResult> UpdatePasswordHash(IUserPasswordStore<TUser> passwordStore, TUser user, string? newPassword, bool validatePassword = true, CancellationToken cancellationToken = default(CancellationToken))

-    protected async Task<IdentityResult> ValidateUserAsync(TUser user)
+    protected async Task<IdentityResult> ValidateUserAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))

-    protected async Task<IdentityResult> ValidatePasswordAsync(TUser user, string? password)
+    protected async Task<IdentityResult> ValidatePasswordAsync(TUser user, string? password, CancellationToken cancellationToken = default(CancellationToken))

-    protected virtual async Task<IdentityResult> UpdateUserAsync(TUser user)
+    protected virtual async Task<IdentityResult> UpdateUserAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
}

public class SignInManager<TUser> where TUser : class
{
-    public virtual async Task<ClaimsPrincipal> CreateUserPrincipalAsync(TUser user)
+    public virtual async Task<ClaimsPrincipal> CreateUserPrincipalAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<bool> CanSignInAsync(TUser user)
+    public virtual async Task<bool> CanSignInAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task RefreshSignInAsync(TUser user)
+    public virtual async Task RefreshSignInAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual Task SignInAsync(TUser user, bool isPersistent, string? authenticationMethod = null)
+    public virtual Task SignInAsync(TUser user, bool isPersistent, string? authenticationMethod = null, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual Task SignInAsync(TUser user, AuthenticationProperties authenticationProperties, string? authenticationMethod = null)
+    public virtual Task SignInAsync(TUser user, AuthenticationProperties authenticationProperties, string? authenticationMethod = null, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual Task SignInWithClaimsAsync(TUser user, bool isPersistent, IEnumerable<Claim> additionalClaims)
+    public virtual Task SignInWithClaimsAsync(TUser user, bool isPersistent, IEnumerable<Claim> additionalClaims, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task SignInWithClaimsAsync(TUser user, AuthenticationProperties? authenticationProperties, IEnumerable<Claim> additionalClaims)
+    public virtual async Task SignInWithClaimsAsync(TUser user, AuthenticationProperties? authenticationProperties, IEnumerable<Claim> additionalClaims, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task SignOutAsync()
+    public virtual async Task SignOutAsync(CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<TUser?> ValidateSecurityStampAsync(ClaimsPrincipal? principal)
+    public virtual async Task<TUser?> ValidateSecurityStampAsync(ClaimsPrincipal? principal, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<TUser?> ValidateTwoFactorSecurityStampAsync(ClaimsPrincipal? principal)
+    public virtual async Task<TUser?> ValidateTwoFactorSecurityStampAsync(ClaimsPrincipal? principal, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<bool> ValidateSecurityStampAsync(TUser? user, string? securityStamp)
+    public virtual async Task<bool> ValidateSecurityStampAsync(TUser? user, string? securityStamp, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<SignInResult> PasswordSignInAsync(TUser user, string password, bool isPersistent, bool lockoutOnFailure)
+    public virtual async Task<SignInResult> PasswordSignInAsync(TUser user, string password, bool isPersistent, bool lockoutOnFailure, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<SignInResult> PasswordSignInAsync(string userName, string password, bool isPersistent, bool lockoutOnFailure)
+    public virtual async Task<SignInResult> PasswordSignInAsync(string userName, string password, bool isPersistent, bool lockoutOnFailure, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<SignInResult> CheckPasswordSignInAsync(TUser user, string password, bool lockoutOnFailure)
+    public virtual async Task<SignInResult> CheckPasswordSignInAsync(TUser user, string password, bool lockoutOnFailure, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<bool> IsTwoFactorClientRememberedAsync(TUser user)
+    public virtual async Task<bool> IsTwoFactorClientRememberedAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task RememberTwoFactorClientAsync(TUser user)
+    public virtual async Task RememberTwoFactorClientAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual Task ForgetTwoFactorClientAsync()
+    public virtual Task ForgetTwoFactorClientAsync(CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<SignInResult> TwoFactorRecoveryCodeSignInAsync(string recoveryCode)
+    public virtual async Task<SignInResult> TwoFactorRecoveryCodeSignInAsync(string recoveryCode, CancellationToken cancellationToken = default(CancellationToken))

-    private async Task DoTwoFactorSignInAsync(TUser user, TwoFactorAuthenticationInfo twoFactorInfo, bool isPersistent, bool rememberClient)
+    private async Task DoTwoFactorSignInAsync(TUser user, TwoFactorAuthenticationInfo twoFactorInfo, bool isPersistent, bool rememberClient, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<SignInResult> TwoFactorAuthenticatorSignInAsync(string code, bool isPersistent, bool rememberClient)
+    public virtual async Task<SignInResult> TwoFactorAuthenticatorSignInAsync(string code, bool isPersistent, bool rememberClient, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<SignInResult> TwoFactorSignInAsync(string provider, string code, bool isPersistent, bool rememberClient)
+    public virtual async Task<SignInResult> TwoFactorSignInAsync(string provider, string code, bool isPersistent, bool rememberClient, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<TUser?> GetTwoFactorAuthenticationUserAsync()
+    public virtual async Task<TUser?> GetTwoFactorAuthenticationUserAsync(CancellationToken cancellationToken = default(CancellationToken))

-    public virtual Task<SignInResult> ExternalLoginSignInAsync(string loginProvider, string providerKey, bool isPersistent)
+    public virtual Task<SignInResult> ExternalLoginSignInAsync(string loginProvider, string providerKey, bool isPersistent, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<SignInResult> ExternalLoginSignInAsync(string loginProvider, string providerKey, bool isPersistent, bool bypassTwoFactor)
+    public virtual async Task<SignInResult> ExternalLoginSignInAsync(string loginProvider, string providerKey, bool isPersistent, bool bypassTwoFactor, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<IEnumerable<AuthenticationScheme>> GetExternalAuthenticationSchemesAsync()
+    public virtual async Task<IEnumerable<AuthenticationScheme>> GetExternalAuthenticationSchemesAsync(CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<ExternalLoginInfo?> GetExternalLoginInfoAsync(string? expectedXsrf = null)
+    public virtual async Task<ExternalLoginInfo?> GetExternalLoginInfoAsync(string? expectedXsrf = null, CancellationToken cancellationToken = default(CancellationToken))

-    public virtual async Task<IdentityResult> UpdateExternalAuthenticationTokensAsync(ExternalLoginInfo externalLogin)
+    public virtual async Task<IdentityResult> UpdateExternalAuthenticationTokensAsync(ExternalLoginInfo externalLogin, CancellationToken cancellationToken = default(CancellationToken))

-    internal async Task<ClaimsPrincipal> StoreRememberClient(TUser user)
+    internal async Task<ClaimsPrincipal> StoreRememberClient(TUser user, CancellationToken cancellationToken = default(CancellationToken))

-    private async Task<bool> IsTfaEnabled(TUser user)
+    private async Task<bool> IsTfaEnabled(TUser user, CancellationToken cancellationToken = default(CancellationToken))

-    protected virtual async Task<SignInResult> SignInOrTwoFactorAsync(TUser user, bool isPersistent, string? loginProvider = null, bool bypassTwoFactor = false)
+    protected virtual async Task<SignInResult> SignInOrTwoFactorAsync(TUser user, bool isPersistent, string? loginProvider = null, bool bypassTwoFactor = false, CancellationToken cancellationToken = default(CancellationToken))

-    private async Task<TwoFactorAuthenticationInfo?> RetrieveTwoFactorInfoAsync()
+    private async Task<TwoFactorAuthenticationInfo?> RetrieveTwoFactorInfoAsync(CancellationToken cancellationToken = default(CancellationToken))

-    protected virtual async Task<bool> IsLockedOut(TUser user)
+    protected virtual async Task<bool> IsLockedOut(TUser user, CancellationToken cancellationToken = default(CancellationToken))

-    protected virtual Task<SignInResult> LockedOut(TUser user)
+    protected virtual Task<SignInResult> LockedOut(TUser user, CancellationToken cancellationToken = default(CancellationToken))

-    protected virtual async Task<SignInResult?> PreSignInCheck(TUser user)
+    protected virtual async Task<SignInResult?> PreSignInCheck(TUser user, CancellationToken cancellationToken = default(CancellationToken))

-    protected virtual Task ResetLockout(TUser user)
+    protected virtual Task ResetLockout(TUser user, CancellationToken cancellationToken = default(CancellationToken))
}

Usage Examples

public class UserController : Controller
{
    private readonly UserManager<User> _userManager;

    public UserController(UserManager<User> userManager)
    {
      _userManager = userManager;
    }

    [HttpGet("/find")]
    public async Task<IActionResult> FindUserByEmail([FromQuery] string email, CancellationToken cancellationToken)
    {
      var user = _userManager.FindByEmailAsync(email, cancellationToken);
      if (user is null) return NotFound();
      return Ok(user);
    }
}

Risks

There are no risks as the current behavior doesn't rely on the cancellation token as a CancellationToken.None is passed to the method.

TheYoxy avatar Jan 04 '23 14:01 TheYoxy

Thank you for submitting this for API review. This will be reviewed by @dotnet/aspnet-api-review at the next meeting of the ASP.NET Core API Review group. Please ensure you take a look at the API review process documentation and ensure that:

  • The PR contains changes to the reference-assembly that describe the API change. Or, you have included a snippet of reference-assembly-style code that illustrates the API change.
  • The PR describes the impact to users, both positive (useful new APIs) and negative (breaking changes).
  • Someone is assigned to "champion" this change in the meeting, and they understand the impact and design of the change.

ghost avatar Jan 04 '23 16:01 ghost

Thanks for contacting us.

We're moving this issue to the .NET 8 Planning milestone for future evaluation / consideration. We would like to keep this around to collect more feedback, which can help us with prioritizing this work. We will re-evaluate this issue, during our next planning meeting(s). If we later determine, that the issue has no community involvement, or it's very rare and low-impact issue, we will close it - so that the team can focus on more important and high impact issues. To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.

ghost avatar Jan 12 '23 19:01 ghost

Seems reasonable to me although I think we would need to add overloads rather than just default parameters to avoid breaking API compatibility if someone just does a runtime upgrade without rebuilding binaries.

mitchdenny avatar Jan 12 '23 22:01 mitchdenny

API Review Notes:

  1. @mitchdenny is right that it would have to be new overloads to be non-breaking.
  2. AspNetUserManager passes in the RequestAborted token from the the IHttpContextAccessor (which is a singleton backed by an AsyncLocal<HttpContext>).
  3. What about existing overrides that don't take the CancellationToken? We still have to call them, right? We could use reflection to detect this and cache the results, but wow!

Given the lengths we would have to go to to make this non-breaking, we cannot approve this now. So far no one has a plan that would make this work with decent performance without breaking. If you really need this functionality you can override UserManager/SignInManager.CancellationToken yourself in the meantime.

halter73 avatar Feb 02 '23 23:02 halter73

Closing as this proposal didn't get approved and a lot of time has passed since then, including many changes have been made to the area.

mkArtakMSFT avatar Dec 01 '23 21:12 mkArtakMSFT