locked
2014-01-16 Nightly Build blew away UserManager.PasswordResetTokens, UserManager.UserConfirmationTokens RRS feed

  • Question

  • User1709456562 posted

    One speck of documentation would go a long way. A short sample of how to implement password reset validation and user confirmation would be greatly appreciated.

    The following code worked until this morning. In the constructor:

    if (Startup.DataProtectionProvider != null)
    {
       this.UserManager.PasswordResetTokens = new DataProtectorTokenProvider(Startup.DataProtectionProvider.Create("PasswordReset"));
       this.UserManager.UserConfirmationTokens = new DataProtectorTokenProvider(Startup.DataProtectionProvider.Create("ConfirmUser"));
    }

    ... in the Password Reset Task<ActionResult>:

    var t = UserManager.PasswordResetTokens.Validate(emailedToken);
    if (t == null)
    {
        ModelState.AddModelError("""Invalid token.");
        return View(model);
    }
    if (t.CreationDate < DateTime.UtcNow.AddDays(-1))
    {
        ModelState.AddModelError("""The token has expired (only valid for one day).");
        return View(model);
    }
     
    //reset the password
    var uid = t.UserId;
    
    Friday, January 17, 2014 9:34 AM

All replies

  • User521424079 posted

    Hi,

    There isn't any built in data annotation for this. You could create your custom attribute to do the validation, but it's not easy. As such, I would suggest you to use Jquery Validation / Javascript to handle this.

    Basically you would want to override the submit event and do your own validation logic in there. You code will be similar to this:

    function SubmitToServer() {
        if ($('#Password').length == 0 || ($('#Password').length > 0 && $('#NewPassword ').length > 1 && $(formId).valid()) {
            $(formId).submit();
        }
    }

    Hope it helps.

    Monday, January 20, 2014 5:12 AM
  • User1709456562 posted

    Hi Betsy,

    Thanks for replying. Unfortunately, you've replied to the wrong question. My post deals with AspNet.Identity, which -- until a couple of days ago -- provided a nice mechanism to validate tokens sent by email to users in the two cases I listed: when they request a password reset and when they register on the site. So, this has nothing to do with database access or Entity Framework model, or data annotations. The code I show in the original post worked great, but with the nightly update a few days ago, it does not. I had to roll back the update. The new code that was pushed on the Nightly Builld does not and cannot work (asks for a userId at password validation, which the framework is supposed to return to me if the token is valid and has not expired. I do not have a userId at that ponit...)

    Best,

    John

    Monday, January 20, 2014 10:22 AM
  • User401360897 posted
    ASP.NET 2.0 Identity i snow RTM. You can create an empty asp.net application and Install-Package Microsoft.AspNet.Identity.Samples -Pre
    Saturday, March 22, 2014 2:46 PM
  • User-573384812 posted

    This has reached production and broke my existing code, have you figured out the alternative to using PasswordResetTokens and UserConfirmationTokens?

    Sunday, March 23, 2014 11:22 AM
  • User1709456562 posted

    Hi Shawn. Sorry to say I have not. I am still using my original solution, as the documentation of ASP.NET 2.0 Identity is scary bad. The sample project does not deal with real-world issues like registration and password change/reset processes. Its home page has gems like this (under "Social Logins"):

    The first link on the page (http://www.asp.net/aspnet/identity) is broken. Thus far, Identity 2 might be OK to play around with 3rd party authentication providers but it is surely not ready for production environments where real work is done. It is a giant FAIL on some of the most basic requirements. 

    Sunday, March 23, 2014 11:38 AM
  • User401360897 posted

    ShawnMclean

    This has reached production and broke my existing code, have you figured out the alternative to using PasswordResetTokens and UserConfirmationTokens?

    Note PasswordResetTokens and UserConfirmationTokens are replaced with UserTokenProvider property in Beta1(and same in RTM),

    manager.SmsService = new SmsService();
                var dataProtectionProvider = options.DataProtectionProvider;
                if (dataProtectionProvider != null)
                {
                    manager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));
                }

    Also you can try a sample app by creating an empty asp.net application and Install-Package Microsoft.AspNet.Identity.Samples -Pre

    Sunday, March 23, 2014 11:50 AM
  • User1709456562 posted

    Hi Imran, thanks for your post. Could you please show us how to perform the PasswordResetToken and UserConfirmationToken validation? The token is sent to a user via email. The user clicks the confirmation link. At this point the page has no clue aboout the user, all it knows is the token. How do I get the userId, or userName, or userEmail form the token provided? Step-by-step documentation would be preferred, but an example would also suffice. 

    Sunday, March 23, 2014 12:50 PM
  • User1709456562 posted

    Imran, 

    Note PasswordResetTokens and UserConfirmationTokens are replaced with UserTokenProvider property in Beta1(and same in RTM),

    Yet, in the sample app you reference is the following line of code:

    var code = await UserManager.GeneratePasswordResetTokenAsync(user.Id);

    My question is simple. Are PasswordResetTokens in or out?
    Moreover, the sample project emails the UserId in plain text as a part of the reset link. Does anyone see a problem with this:

    var callbackUrl = Url.Action("ResetPassword", "Account", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme);

    Sunday, March 23, 2014 1:06 PM
  • User401360897 posted

    My question is simple. Are PasswordResetTokens in or out?

    Could you please show us how to perform the PasswordResetToken and UserConfirmationToken validation?

    As I told before the identity framework now using UserTokenProvider for both. Just see the decompiled code glimpse,

        public virtual async Task<string> GeneratePasswordResetTokenAsync(TKey userId)
            {
                this.ThrowIfDisposed();
                return await this.GenerateUserTokenAsync("ResetPassword", userId);
            }
    
     public virtual async Task<string> GenerateUserTokenAsync(string purpose, TKey userId)
            {
                this.ThrowIfDisposed();
                if (this.UserTokenProvider == null)
                {
                    throw new NotSupportedException(Resources.NoTokenProvider);
                }
                ConfiguredTaskAwaitable<TUser> configuredTaskAwaitable = this.FindByIdAsync(userId).ConfigureAwait(false);
                TUser tUser = await configuredTaskAwaitable;
                if (tUser == null)
                {
                    CultureInfo currentCulture = CultureInfo.CurrentCulture;
                    string userIdNotFound = Resources.UserIdNotFound;
                    object[] objArray = new object[] { userId };
                    throw new InvalidOperationException(string.Format(currentCulture, userIdNotFound, objArray));
                }
                ConfiguredTaskAwaitable<string> configuredTaskAwaitable1 = this.UserTokenProvider.GenerateAsync(purpose, this, tUser).ConfigureAwait(false);
                return await configuredTaskAwaitable1;
            }
    

    The token is sent to a user via email. The user clicks the confirmation link. At this point the page has no clue aboout the user, all it knows is the token. How do I get the userId, or userName, or userEmail form the token provided?

    Yes the user only have userId and token. The validation of token is done in ResetPassword action using,

    var result = await UserManager.ResetPasswordAsync(user.Id, model.Code, model.Password);


    which will validate that the token is belonging to the current user. You can also set TokenLifespan,

    manager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity")) {TokenLifespan = TimeSpan.FromHours(1) };

    Moreover, the sample project emails the UserId in plain text as a part of the reset link. Does anyone see a problem with this:
    var callbackUrl = Url.Action("ResetPassword", "Account", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme);

    Yes you are right, it is superfluous. You can simply remove it.

    Sunday, March 23, 2014 3:16 PM
  • User-1072315183 posted

    jkorondy

    The token is sent to a user via email. The user clicks the confirmation link. At this point the page has no clue aboout the user, all it knows is the token. How do I get the userId, or userName, or userEmail form the token provided?

    Yes the user only have userId and token. The validation of token is done in ResetPassword action using,

    I am sorry, but original question was how to obtain an UserId from a token. I have a exactly the same problem. I KNOW how to reset password knowning UserId AND token. Question was how to GET UserId from token (another words, how to reset a password knowing ONLY token and NOT UserId).

    Lets forget about password for a while, I just need to have an UserId from a token - this wass possible in Identity 1.1 but is it possible in 2.0?

    Wednesday, June 25, 2014 8:36 AM
  • User401360897 posted

    I think what you are asking is how OWIN Transform cookie into Identity(whihc includes the Id). You can find this by seeing,

    http://katanaproject.codeplex.com/SourceControl/latest#src/Microsoft.Owin.Security.Cookies/CookieAuthenticationHandler.cs

    Wednesday, June 25, 2014 8:55 AM