Is it possible to test whether a confirm email token is expired using Identity Framework\'s UserManager
? No matter what the error is, from the following:
Here comes an .NET Core 2.1 adaption of the solution provided by @Nkosi :
ApplicationUser class
public class ApplicationUser : IdentityUser
{
public string EmailConfirmationToken { get; set; }
public string ResetPasswordToken { get; set; }
}
Derived UserManager class
public class CustomUserManager : UserManager
{
public CustomUserManager(IUserStore store,
IOptions optionsAccessor,
IPasswordHasher passwordHasher,
IEnumerable> userValidators,
IEnumerable> passwordValidators,
ILookupNormalizer keyNormalizer,
IdentityErrorDescriber errors,
IServiceProvider services,
ILogger> logger)
: base(store, optionsAccessor, passwordHasher, userValidators, passwordValidators, keyNormalizer, errors, services, logger)
{
}
public override async Task GenerateEmailConfirmationTokenAsync(ApplicationUser user)
{
/* NOTE:
* The default UserTokenProvider generates tokens based on the users's SecurityStamp, so until that changes
* (like when the user's password changes), the tokens will always be the same, and remain valid.
* So if you want to simply invalidate old tokens, just call manager.UpdateSecurityStampAsync().
*/
//await base.UpdateSecurityStampAsync(userId);
var token = await base.GenerateEmailConfirmationTokenAsync(user);
if (!string.IsNullOrEmpty(token))
{
user.EmailConfirmationToken = token; //<<< Last issued token
//Note: If a token is generated then the current email is no longer confirmed.
user.EmailConfirmed = false;
await UpdateAsync(user);
}
return token;
}
public override async Task ConfirmEmailAsync(ApplicationUser user, string token)
{
if (user == null)
{
return IdentityResult.Failed(new IdentityError {Description = "User not found."});
}
var result = await base.ConfirmEmailAsync(user, token);
if (result.Succeeded)
{
user.EmailConfirmationToken = null;
return await UpdateAsync(user);
}
else if (user.EmailConfirmationToken == token)
{
//Previously Issued Token expired
result = IdentityResult.Failed(new IdentityError { Description = "Expired token." });
}
return result;
}
}
UserManager Extension
public static class ApplicationUserManagerExtension
{
public static Task FindIdByEmailConfirmationTokenAsync(this UserManager manager, string confirmationToken)
{
string result = null;
ApplicationUser user = manager.Users
.SingleOrDefault(u => u.EmailConfirmationToken != null && u.EmailConfirmationToken == confirmationToken);
if (user != null)
{
result = user.Id;
}
return Task.FromResult(result);
}
}
Update: The CustomUserManager has to be added to services in Startup.cs in ConfigureServices Method.
services.AddTransient();
Without this, DependencyInjection fails.