ResetPassword Token How and where is it stored?
I was trying to figure out how password reset and account confirmation works in ASP.NET Identity. I just would like to know if tokens are stored and if so where?
The links I get when I use the password reset function look something like this.
http://localhost:1470/Account/ResetPassword?userId=a8b1389c-df93-4dfc-b463-541507c1a4bc&code=yhUegXIM9SZBpPVbBtv22kg7NO7F96B8MJi9MryAadUY5XYjz8srVkS5UL8Lx%2BLPYTU6a6jhqOrzMUkkMyPbEHPY3Ul6%2B%2F0s0qQvtM%2FLLII3s29FgkcK0OnjX46Bmj9JlFCUx53rOH%2FXMacwnKDzoJ1rbrUyypZiJXloIE50Q6iPuMTUHbX9O%2B3JMZtCVXjhhsHLkTOn9IVoN6uVAOMWNQ%3D%3D
My guess is the tokens are stored in the link itself, as I cannot find it anywhere else. Maybe someone knows for sure?
source to share
@DSR is correct, but I would like to add some information to this as well.
If you set up a web project from Individual User Accounts
go to Individual User Accounts
:
App_Start -> IdentityConfig.cs
There you will see code like this:
var dataProtectionProvider = options.DataProtectionProvider;
if (dataProtectionProvider != null)
{
manager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));
}
Description for DataProtectorTokenProvider<TUser, TKey>
gives information:
Represents a token provider that uses IDataProtector to generate encrypted tokens based on a security token.
https://docs.microsoft.com/en-us/previous-versions/aspnet/dn613280(v%3dvs.108)
However, we can try to understand a little deeper how it actually works. Token validation will fail if different ones are used to create and validate a token on the same server Application Pool Identities
. This indicates that the actual protection mechanism will look something like this:
System.Security.Cryptography.ProtectedData.Protect(userData, entropy, DataProtectionScope.CurrentUser);
Considering that this works if all sites use the same Application Pool Identity
it also points to Application Pool Identity
. Can also be DataProtectionProvider
with protectionDescriptor
"LOCAL=user"
. It had to work with different ones Application Pool Identities
if given LOCAL=machine
.
new DataProtectionProvider("LOCAL=user")
dataProtectionProvider
has a type IDataProtectionProvider
.
This is introduced in Startup.Auth.cs like this:
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
CreatePerOwinContext
is in assembly Microsoft.AspNet.Identity.Owin
→ AppBuilderExtensions.cs
. And ASP.NET Identity
and ASP.NET Core Identity
are open source and can be viewed on GitHub.
public static IAppBuilder CreatePerOwinContext<T>(this IAppBuilder app,
Func<IdentityFactoryOptions<T>, IOwinContext, T> createCallback,
Action<IdentityFactoryOptions<T>, T> disposeCallback) where T : class, IDisposable
{
if (app == null)
{
throw new ArgumentNullException("app");
}
if (createCallback == null)
{
throw new ArgumentNullException("createCallback");
}
if (disposeCallback == null)
{
throw new ArgumentNullException("disposeCallback");
}
app.Use(typeof (IdentityFactoryMiddleware<T, IdentityFactoryOptions<T>>),
new IdentityFactoryOptions<T>
{
DataProtectionProvider = app.GetDataProtectionProvider(),
Provider = new IdentityFactoryProvider<T>
{
OnCreate = createCallback,
OnDispose = disposeCallback
}
});
return app;
}
app.GetDataProtectionProvider()
in turn app.GetDataProtectionProvider()
is in the assembly, Microsoft.Owin.Security
which is also Open Source.
public static IDataProtectionProvider GetDataProtectionProvider(this IAppBuilder app)
{
if (app == null)
{
throw new ArgumentNullException("app");
}
object value;
if (app.Properties.TryGetValue("security.DataProtectionProvider", out value))
{
var del = value as DataProtectionProviderDelegate;
if (del != null)
{
return new CallDataProtectionProvider(del);
}
}
return null;
}
We also see that it CreateDataProtector
has a fallback to implement DpapiDataProtectionProvider
.
private static IDataProtectionProvider FallbackDataProtectionProvider(IAppBuilder app)
{
return new DpapiDataProtectionProvider(GetAppName(app));
}
When reading about DpapiDataProtectionProvider
(DPAPI stands for Data Protection Application Programming Interface), the description says:
Used to provide data protection services that are derived from the Data Protection API. It is the best choice for data protection when your application is not hosted in ASP.NET and all processes run under the same domain identity .
The goals of the Create method are described as:
The additional entropy used to ensure the protection of protected data can only be unprotected for the right purpose.
The class of the defender itself then looks like this:
using System.Security.Cryptography;
namespace Microsoft.Owin.Security.DataProtection
{
internal class DpapiDataProtector : IDataProtector
{
private readonly System.Security.Cryptography.DpapiDataProtector _protector;
public DpapiDataProtector(string appName, string[] purposes)
{
_protector = new System.Security.Cryptography.DpapiDataProtector(appName, "Microsoft.Owin.Security.IDataProtector", purposes)
{
Scope = DataProtectionScope.CurrentUser
};
}
public byte[] Protect(byte[] userData)
{
return _protector.Protect(userData);
}
public byte[] Unprotect(byte[] protectedData)
{
return _protector.Unprotect(protectedData);
}
}
}
https://docs.microsoft.com/en-us/previous-versions/aspnet/dn253784(v%3dvs.113)
source to share