Reputation: 805
I am on Asp.Net core with .Net 5.0 In startup I have added;
services.AddIdentity<ApplicationUser, ApplicationRole>(SetupIdentityOptions)
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.Configure<DataProtectionTokenProviderOptions>(opt =>
{
opt.TokenLifespan = TimeSpan.FromDays(1);
}
);
I generate the code as below(encoding done as per the MS docs);
var code = await CommonServices.UserManager.GeneratePasswordResetTokenAsync(user);
code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
var callbackUrl = $"{request.RequestData.ReturnUrl}?code={code}";
Now if I save the code generated at this point and check the code received to controller after user clicks the link they are identical. However when I do;
var result = await CS.UserManager.ResetPasswordAsync(user, model.Code, model.Password);
it gives me "Invalid Token" however tokens are identical.
Then I tried this and still says invalid token;
var isValidToken = await _userManager.VerifyUserTokenAsync(
user,
_userManager.Options.Tokens.PasswordResetTokenProvider,
UserManager<TUser>.ResetPasswordTokenPurpose,
code);
I am not sure whether the Identity framework saves the generated tokens in [AspNetUserTokens] table. I can't find any saved tokens after a generating the token.
What may be the problem?
Upvotes: 3
Views: 1463
Reputation: 11
I encountered the issue while configuring MFA during first login, where I offered users the choice of authentication methods: Email, SMS, or Authenticator App. The issue occurred only when the Authenticator App was selected.
After investigation, we found that configuring the Authenticator App resets the SecurityStamp for the user in the AspNetUsers table. So, any tokens generated before this reset are rendered invalid.
To resolve the issue, we adjusted our flow as follows:
Check if the Authenticator App is configured: Before proceeding with actions like password reset, confirm whether the user has completed MFA setup with the Authenticator App.
Generate a new token: After the Authenticator App is set up, create a fresh token and validate the user with this token.
Upvotes: 0
Reputation: 805
My bad, I had to convert the encoded string back which I haven't done.
So, since I used
code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
After user clicks the link, I have to;
var bytes = WebEncoders.Base64UrlDecode(model.Code);
var code = Encoding.UTF8.GetString(bytes);
and then call
ResetPasswordAsync(user, code, model.Password);
which worked
Upvotes: 3