ResetPassword Token How and where is it stored?

后端 未结 2 1132
野趣味
野趣味 2020-12-19 10:39

I\'ve been trying to understand how the reset password & account confirmation works in ASP.NET Identity. I\'d just like to know if the Tokens are being stored and if so,

相关标签:
2条回答
  • 2020-12-19 11:21

    As I mentioned in the comment

    "Tokens are generated using the SecurityStamp and validating against the SecurityStamp and not storing anywhere in database or local file storage. If you update the SecurityStamp, then previous tokens are no longer valid."

    0 讨论(0)
  • 2020-12-19 11:24

    @DSR is correct but I would like to add some information to this as well.

    If you have set up a Web project with Individual User Accounts go to:

    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"));
    }
    

    The description for DataProtectorTokenProvider<TUser, TKey> gives the information:

    Represents a token provider that uses an IDataProtector to generate encrypted tokens based off of the security stamp.

    https://docs.microsoft.com/en-us/previous-versions/aspnet/dn613280(v%3dvs.108)

    We can however try to dig a bit deeper how it really works. The token verification will fail if different Application Pool Identities are used for creating and validating a token on a single server. This points to that the actual protection mechanism would look something like this:

    System.Security.Cryptography.ProtectedData.Protect(userData, entropy, DataProtectionScope.CurrentUser);
    

    Given that it works if all sites use the same Application Pool Identity points to this as well. Could also be DataProtectionProvider with protectionDescriptor "LOCAL=user". It should have worked with different Application Pool Identities if LOCAL=machine was set.

    new DataProtectionProvider("LOCAL=user")
    

    https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.dataprotector?view=netframework-4.7.2

    https://docs.microsoft.com/en-us/uwp/api/windows.security.cryptography.dataprotection.dataprotectionprovider

    dataProtectionProvider is of type IDataProtectionProvider.

    It is injected in Startup.Auth.cs like this:

    app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
    

    CreatePerOwinContext is located in the assembly Microsoft.AspNet.Identity.Owin -> AppBuilderExtensions.cs. Both ASP.NET Identity and ASP.NET Core Identity are open source and can be viewed at 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;
    }
    

    https://github.com/aspnet/AspNetIdentity/blob/master/src/Microsoft.AspNet.Identity.Owin/Extensions/AppBuilderExtensions.cs

    https://archive.codeplex.com/?p=aspnetidentity#src/Microsoft.AspNet.Identity.Owin/Extensions/AppBuilderExtensions.cs

    app.GetDataProtectionProvider() is in turn located in assembly Microsoft.Owin.Security that 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;
    }
    

    https://github.com/aspnet/AspNetKatana/blob/release/src/Microsoft.Owin.Security/DataProtection/AppBuilderExtensions.cs

    We can also see that CreateDataProtector has a fallback to the implementation 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 the data protection services that are derived from the Data Protection API. It is the best choice of data protection when you application is not hosted by ASP.NET and all processes are running as the same domain identity.

    The Create method purposes are described as:

    Additional entropy used to ensure protected data may only be unprotected for the correct purposes.

    The protector class 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)

    0 讨论(0)
提交回复
热议问题