ASP.NET Identity WebAPI无效密码重置令牌

时间:2016-01-26 16:02:47

标签: c# asp.net-mvc asp.net-web-api2 asp.net-identity-2

我有一个Webapi服务,可以生成密码重置令牌 令牌生成服务终点:

    [Authorize(Users = "abcd")]
    [HttpGet]
    [ActionName("GenerateForgotPasswordToken")]
    public async Task<IHttpActionResult> GenerateForgotPasswordToken(string key)
    {
        if (key == null || UserManager.FindById(key) == null)
        {
            return InternalServerError(new Exception("User not found"));
        }
        return Ok(await UserManager.GeneratePasswordResetTokenAsync(key));
    }

我的应用程序UserManager:

    public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
    {
        //var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<ApplicationDbContext>()));
        var manager = new ApplicationUserManager(new UserStore<IdentityUser>(new MTA()));
        // Configure validation logic for usernames
        manager.UserValidator = new UserValidator<IdentityUser>(manager)
        {
            AllowOnlyAlphanumericUserNames = false,
            RequireUniqueEmail = true
        };
        // Configure validation logic for passwords
        manager.PasswordValidator = new PasswordValidator
        {
            RequiredLength = 6,
            RequireNonLetterOrDigit = true,
            RequireDigit = true,
            RequireLowercase = true,
            RequireUppercase = true,
        };
        var dataProtectionProvider = options.DataProtectionProvider;
        if (dataProtectionProvider != null)
        {
            manager.UserTokenProvider = new DataProtectorTokenProvider<IdentityUser>(dataProtectionProvider.Create("ASP.NET Identity"));
        }
        return manager;
    }

将在电子邮件中使用令牌向用户发送密码重置URL。该URL指向ASP.NET MVC视图,它是我的WebAPI项目的一部分,显然托管在IIS中的同一Web应用程序中。页面上的密码重置按钮调用我的其他服务端点,重置密码 Passowrd重置服务终点:

    [HttpGet]
    [AllowAnonymous]
    public async Task<HttpResponseMessage> ResetPassword([FromUri]string email,[FromUri]string code,[FromUri]string password)
    {
        var user = await UserManager.FindByEmailAsync(email);
        var result = await UserManager.ResetPasswordAsync(user.Id, code, password);
        if (result.Succeeded)
        {
            return Request.CreateResponse();
        }
        return Request.CreateResponse(System.Net.HttpStatusCode.Ambiguous);
    }

同样可以提一下,这两个web api端点都在同一个控制器中,在控制器中我定义了一个全局UserManger,如下所示:

    private ApplicationUserManager _userManager;
    public ApplicationUserManager UserManager
    {
        get
        {
            return _userManager ?? Request.GetOwinContext().GetUserManager<ApplicationUserManager>();
        }
        private set
        {
            _userManager = value;
        }
    }

当我使用高级REST客户端等外部工具时,我能够点击第一个端点生成令牌,然后将令牌连同电子邮件和新密码一起传递到第二个端点,并成功重置密码。但是,当我的ASP.NET MVC控制器使用第一个端点生成的相同令牌并调用passwordReset端点时,令牌无效!我已经确定没有编码/解码问题,并且第二个端点接收的令牌在两个测试中都是相同的。
我的所有WebApi和ASP控制器都在同一个项目中并托管在同一个Web应用程序中。 我认为问题可能与基于 OwinContext 的请求提交时有一个新的令牌提供程序有关,但我不明白为什么它可以通过Web浏览器调用它

 public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)

1 个答案:

答案 0 :(得分:1)

我在阅读完这个问题后发现了这个问题: Make ASP.NET Identity 2.0 Email confirm token work for WCF and MVC

在我的情况下,IIS配置为在运行时生成机器密钥,这就是令牌无效的原因,即使我的所有代码都作为单个应用程序运行。 Automatically generate at runtime should be unchecked

以下是IIS计算机密钥配置的指南:How to Generate Machine Key using IIS