5

I am using this code to generate password reset links:

    private async Task<string> GetNewEmailConfirmationLink(ApplicationUser user)
    {
        var code = await this.UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
        var callbackUrl = Url.Action(
           "ConfirmEmail",
           "Account",
           new { userId = user.Id, code = code },
           protocol: Request.Url.Scheme);
        return callbackUrl;
    }

In principle, this code works just fine - but the link generated is extremely long. While secure, this links needs sometimes to be copy pasted etc. and then it's length tends to cause errors (forgotten elements etc.). Is there any way to shorten this?

An generated link as example: http://example.com:9999/de-DE/Account.aspx/ConfirmEmail?userId=1f4f605a-1be5-4b79-9fb0-139687fe8edc&code=0AjkI5qK917WkZw%2Bz0nXf1uK%2BK9bvYAK6BNEVM2l%2Fc%2BlBYOIiitrQ0gMUrB96CCNYc11hnpNpp2Wg2buC548mAb8l9JwzcwfuOiMAXiwJ%2F3iDH1LlXWgiLW%2FXxcVqLEs2hIhvmye2%2FJxQZD3RcODyNyGD%2FnWjrJRoFK%2B16FtyrtimfNRL%2F1L9vgrk5HiWENn

Christian Sauer
  • 10,351
  • 10
  • 53
  • 85
  • In addition to the provided question, have a look on this answer: http://stackoverflow.com/a/23661872/809357 easy to implement and resulting code can be shorter. – trailmax Dec 11 '14 at 15:22

3 Answers3

4

For ASP.NET Core, yup we can make short, less headache.

    services.AddIdentity<ApplicationUser, ApplicationRole>(options => {
        options.Tokens.PasswordResetTokenProvider = TokenOptions.DefaultEmailProvider;
        options.Tokens.EmailConfirmationTokenProvider = TokenOptions.DefaultEmailProvider;
    }).AddDefaultTokenProviders()
    .AddEntityFrameworkStores<YourDbContext>();
hubert17
  • 285
  • 5
  • 8
3

There are two ways to achieve this which come to my mind.

One is to shorten the generated code itself. This means that you give a shorter version (generated from the original code) and use it for all the user interaction. Before confirming the email address of the user you convert the link to its original representation.

The other option is to implement the IUserTokeProvider which creates your own token.

Horizon_Net
  • 5,959
  • 4
  • 31
  • 34
1
services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
    options.Tokens.EmailConfirmationTokenProvider = TokenOptions.DefaultEmailProvider;
})
.AddDefaultTokenProviders();

Found out, after some digging, that the default EmailTokenProvider generates exactly the six digits you're looking for but that by default it is wrapped into a DataProtectorTokenProvider that scrambles the output.

By 'resetting' the EmailConfirmationTokenProvider to TokenOptions.DefaultEmailProvider you unwrap it and get the normal unscrambled token when invoking the GenerateEmailConfirmationTokenAsync method.

I see my answer matches https://stackoverflow.com/a/54523545/129269 but I didn't figure that out without knowing the background.

riezebosch
  • 1,950
  • 16
  • 29