How to implement a TokenProvider in ASP.NET Identi

2019-03-16 14:24发布

问题:

I'm trying to implement password reset functionality with nightly build of ASP.NET Identity 1.1. There is a UserManager.GetPasswordResetToken method, but it throws an exception "No ITokenProvider is registered". Is there an built in token provider in ASP.NET Identity? If yes, how I can register it? If no, how I can implement one? Will be default Token Provider in the 1.1. release? And final question, is there an estimated 1.1 release date?

回答1:

The default token provider implementation is found in the Microsoft.Identity.Owin package:

/// <summary>
/// Token provider that uses a DataProtector to generate encrypted tokens
/// </summary>
public class DataProtectorTokenProvider : ITokenProvider {
    public DataProtectorTokenProvider(IDataProtector protector)

And you do something like this to wire one up using the default data protection provider from your OWIN IAppBuilder

IDataProtectionProvider provider = app.GetDataProtectionProvider();
if (provider != null)
{
    manager.PasswordResetTokens = new DataProtectorTokenProvider(provider.Create("PasswordReset"));
    manager.UserConfirmationTokens = new DataProtectorTokenProvider(provider.Create("ConfirmUser"));
}


回答2:

If someone looking for solution under AspNet.Identity 2.0 beta1 version.

Only this need to be modified.

UserManager.UserTokenProvider = new DataProtectorTokenProvider
<SecurityUser, string>(provider.Create("UserToken")) 
as IUserTokenProvider<SecurityUser, string>;

PasswordResetTokens and UserConfirmationTokens is merged into UserTokenProvider property and token provider class is also modified.



回答3:

Another way to do this (building on the other answers but simplifying it some) is to change Startup.Auth.cs so it looks similar to this:

public partial class Startup
{
    internal static IDataProtectionProvider DataProtectionProvider { get; private set; }

    public void ConfigureAuth(IAppBuilder app)
    {
        DataProtectionProvider = app.GetDataProtectionProvider();
    }
}

Then, modify the default constructor in AccountController.cs so that it looks similar to this:

 public AccountController()
     : this(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext())))
 {
     if (Startup.DataProtectionProvider != null)
     {
         this.UserManager.PasswordResetTokens = new DataProtectorTokenProvider(Startup.DataProtectionProvider.Create("PasswordReset"));
         this.UserManager.UserConfirmationTokens = new DataProtectorTokenProvider(Startup.DataProtectionProvider.Create("ConfirmUser"));
     }
 }


回答4:

Ok, answering my own question based on @hao-kung reply. First add static constructor and UserManagerFactory to Statrup class (startup.auth.cs)

public partial class Startup
{
    static Startup()
    {
        UserManagerFactory = () => new UserManager<IdentityUser>(new UserStore<IdentityUser>());
    }

    public static Func<UserManager<IdentityUser>> UserManagerFactory { get; set; }

    public void ConfigureAuth(IAppBuilder app)
    {
        var manager = UserManagerFactory();
        IDataProtectionProvider provider = app.GetDataProtectionProvider();
        if (provider != null)
        {
            manager.PasswordResetTokens = new DataProtectorTokenProvider(provider.Create("PasswordReset"));
            manager.UserConfirmationTokens = new DataProtectorTokenProvider(provider.Create("ConfirmUser"));
        }


        app.UseCookieAuthentication(new CookieAuthenticationOptions());
        app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
    }
}

Then init UserManager in the AccountController using that UserManagerFactory

public AccountController() : this(Startup.UserManagerFactory())
{
}

public AccountController(UserManager<IdentityUser> userManager)
{
    UserManager = userManager;
}

public UserManager<IdentityUser> UserManager { get; private set; }