Reputation: 367
Is there any ways to see the generated Password Reset Tokens in ASP.NET Identity 2 ?
My assumption is there should be a dictionary in TokenProvider
which holds those tokens in memory.
Update:
Here is a similar question ResetPassword Token How and where is it stored?
"Tokens are generated using the SecurityStamp and validating against the SecurityStamp and not storing anywhere in database or local file storage."
But still the question is how does the framework know when a token is expired without storing it?
Upvotes: 5
Views: 6790
Reputation: 62260
Token is not stored in Memory instead it is generated on the fly from the given SecurityStamp. Token is basically an Unicode encoded string.
You can see UserManager.cs's CreateSecurityTokenAsync method.
internal async Task<byte[]> CreateSecurityTokenAsync(TUser user)
{
return Encoding.Unicode.GetBytes(await GetSecurityStampAsync(user));
}
Upvotes: 4
Reputation: 247108
As mentioned by one of the commenters
"Tokens are generated using the SecurityStamp and validated against the SecurityStamp and not stored anywhere in database or local file storage."
which was quoted from ResetPassword Token How and where is it stored?
Here is how I was able to persist the tokens for later use.
I am assuming you are using the default project template.
In ApplicationUser
create properties to store the tokens.
public class ApplicationUser : IdentityUser {
public string EmailConfirmationToken { get; set; }
public string ResetPasswordToken { get; set; }
}
Create the respective columns in the AspNetUsers
table.
I then updated the ApplicationUserManager
class as follows.
public override async System.Threading.Tasks.Task<string> GenerateEmailConfirmationTokenAsync(string userId) {
/* 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(userId);
//associate the email token with the user account
if (!string.IsNullOrEmpty(token)) {
var x = await FindByIdAsync(userId);
x.EmailConfirmationToken = token;
x.EmailConfirmed = false;
await UpdateAsync(x);
}
return token;
}
public override async System.Threading.Tasks.Task<string> GeneratePasswordResetTokenAsync(string userId) {
var token = await base.GeneratePasswordResetTokenAsync(userId);
if (!string.IsNullOrEmpty(token)) {
var x = await FindByIdAsync(userId);
x.ResetPasswordToken = token;
await UpdateAsync(x);
}
return token;
}
public override async System.Threading.Tasks.Task<IdentityResult> ConfirmEmailAsync(string userId, string token) {
var result = await base.ConfirmEmailAsync(userId, token);
if (result.Succeeded) {
var x = await FindByIdAsync(userId);
x.EmailConfirmationToken = null;
await UpdateAsync(x);
}
return result;
}
public override async System.Threading.Tasks.Task<IdentityResult> ResetPasswordAsync(string userId, string token, string newPassword) {
var result = await base.ResetPasswordAsync(userId, token, newPassword);
if (result.Succeeded) {
var x = await FindByIdAsync(userId);
x.ResetPasswordToken = null;
await UpdateAsync(x);
}
return result;
}
The above changes allowed me to persist the tokens between sessions.
Upvotes: 1