Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why am I getting sporadic invalid tokens for email verification in ASP.NET Identity?

I'm trying to figure out why my users are getting frequent invalid tokens when confirming their email. I can't reproduce the issue.

Here's the setup:

userManager.UserTokenProvider = new EmailTokenProvider<User>();

Here's how the token is generated:

var code = await userManager.GenerateEmailConfirmationTokenAsync(user.Id);

Here's how it's verified:

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

I understand that the EmailTokenProvider uses security stamp for invalidation. My understanding is that this stamp only changes when significant changes to the User entity are made like changing password or username. However I'm getting invalid tokens way more frequently for this to be the only explanation.

I'm looking for any pointer that would help me shed some light into why this is occurring.

Edit:

I dug around the source code (documentation is very poor) and as @trailmax pointed out below EmailTokenProvider is wrong for this use-case. It is based on TotpSecurityStampBasedTokenProvider which has hard-coded timeout on tokens to 3 minutes!

like image 323
Kugel Avatar asked Dec 08 '14 21:12

Kugel


People also ask

How do I fix an invalid token?

There are two ways to fix the error: (RECOMMENDED) Change the application signature algorithm to RS256 instead of HS256. Change the value of your responseType parameter to token id_token (instead of the default), so that you receive an access token in the response.

What is invalid token ID?

If you're trying to reset your password and you receive an error citing an “invalid token” or asking you for your token, it's likely that the link you clicked on to reset your password has expired. For security reasons, passwords are never sent out across the Internet.


1 Answers

EmailTokenProvider generates very short-lived token and looks like 6 digits. This token is aimed to be a 2FA and only valid for short period of time (something like 10-15 minutes, don't know the actual value).

The best you can do is to use Identity-provided DataProtectorTokenProvider and that's a bit tricky, because it is not simple to rip it out of OWIN's hands.

The way I go around it is assign static variable in my Start.Auth.cs and then reuse it in UserManager:

public class AuthConfig
{
    public static IDataProtectionProvider DataProtectionProvider { get; set; }

    public void Configuration(IAppBuilder app)
    {
        ConfigureAuth(app);
    }

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

        // do other configuration 
    }
}

And in then re-assign it in constructor of UserManager:

        var dataProtectorProvider = AuthConfig.DataProtectionProvider;
        var dataProtector = dataProtectorProvider.Create("My Asp.Net Identity");
        this.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser, Guid>(dataProtector)
        {
            TokenLifespan = TimeSpan.FromHours(24),
        };

This way you get very long email token that lasts for 24 hours.

I've done the same mistake as you did, but had to correct pretty soon as users complained.

like image 191
trailmax Avatar answered Nov 15 '22 05:11

trailmax