Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET Identity WebAPI invalid password reset token

I have a Webapi service that generates the password Reset token.
Token generation service end point:

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

My application 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;
    }

The token will be used in an email to send a password reset URL to the user. That URL points to an ASP.NET MVC view which is part of my WebAPI project and obviously is hosted in the same web application in IIS. The password reset button on the page calls my other service endpoint which resets the password.
Passowrd reset service end point:

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

Also it might help to mention that both those web api endpoints are in the same controller and in the controller I defined a global UserManger as follows:

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

When I use an external tool like Advanced REST Client, I am able to hit the first endpoint to generate the token and then pass the token to the second endpoint along with email and new password and successfully reset the password. However when my ASP.NET MVC controller uses the same token generated by the first endpoint and call the passwordReset endpoint , the token is invalid! I already make sure that the is no Encoding/Decoding issue and the token that is received by the second end point is identical in both tests.
Once again all my WebApi and ASP controllers are in the same project and hosted in the same web application. I think the problem might be related to having a new Token provider when a request is comming based on the OwinContext but I don't understand why it works calling it through web browser.

 public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
like image 590
Ehsan Avatar asked Nov 08 '22 21:11

Ehsan


1 Answers

I found the problem after reading this question: Make ASP.NET Identity 2.0 Email confirm token work for WCF and MVC

In my case IIS was configured to generate the Machine Key at runtime and that's why the token was invalid even when all my code was running as a single application. Automatically generate at runtime should be unchecked

Here is a guide to IIS machine key configuration :How to Generate Machine Key using IIS

like image 157
Ehsan Avatar answered Nov 15 '22 11:11

Ehsan