ConfirmEmailAsync() getting Invalid Token no matter what

Viewed 428

I am trying to verify the email confirmation token for user but always getting INVALID TOKEN error no matter what I do.

My code is very simple

To Generate the token

EmailVerificationCode = await userManager.GenerateEmailConfirmationTokenAsync(user);
EmailVerificationHTMLFormatCode = HttpUtility.UrlEncode(EmailVerificationCode);

To Verify the Token

 var result = await userManager.ConfirmEmailAsync(user, code);

I always get INVALID TOKEN error.

The things I have tried

  1. Checking both generated token and received token for verification by putting them into the database, they are exactly the same.
  2. Tried using HttpUtility.UrlDecode(Code) to decode the token at receiving end
  3. Tried to just use RAW token without HttpUtility.UrlEncode to verify it

I also went through the following solutions

  1. Asp.net 2.0 Identity, ConfirmEmailAsync() getting Invalid Token
  2. Invalid Token. while verifying email verification code using UserManager.ConfirmEmailAsync(user.Id, code)
  3. AspNet.Identit 2.1.0 ConfirmEmailAsync always returns Invalid token
  4. Asp.NET Identity 2 giving "Invalid Token" error

No matter what I do, it is always an Invalid Token where I can clearly see the token is 100% correct.

Any idea what am I doing wrong?

Edit - If this helps, my Startup.cs has the following Identity configurations

// For Identity
services.AddIdentity<ApplicationUser, IdentityRole>(o =>
   {
     // configure identity options
     o.Password.RequireDigit = false;
     o.Password.RequireLowercase = false;
     o.Password.RequireUppercase = false;
     o.Password.RequireNonAlphanumeric = false;
       o.Password.RequiredLength = 6;
    })
      .AddEntityFrameworkStores<ApplicationDbContext>()
      .AddDefaultTokenProviders();
1 Answers

There are a few questions about this implementation before I answer.

  1. Do you implement a custom DataProtectionProvider?
  2. Do you override the default token life time is x number of hours?

What you can do over come this issue, create a customer DataProtectionProvider like below,

public class EmailConfirmationTokenProvider<TUser> : DataProtectorTokenProvider<TUser> where TUser : class
{
    public EmailConfirmationTokenProvider(IDataProtectionProvider dataProtectionProvider, 
        IOptions<EmailConfirmationTokenProviderOptions> options, 
        ILogger<DataProtectorTokenProvider<TUser>> logger) 
        : base(dataProtectionProvider, options, logger)
    {
    }
}
public class EmailConfirmationTokenProviderOptions : DataProtectionTokenProviderOptions
{
}

Then inject in configure services with lifespan is 2 hours.

 services.AddTokenProvider<EmailConfirmationTokenProvider<User>>("emailconfirmation");

services.Configure(opt => opt.TokenLifespan = TimeSpan.FromHours(3));

Thank you

Related