URL encoding password reset or email confirmation tokens

  • asp.net, identity
  • Asp.Net Identity 2.0 makes it really easy to validate an email address by using the GenerateEmailConfirmationTokenAsync method. However I recently hit an issue where the simplest path, from the same controller, in the same web app, on the same server could not round trip a validation token to confirm the email address.

    Using nancy endpoint to send a code, and then validate the code.

    public class ConfirmEmailModule : NancyModule
    private readonly IdentityUserManager _userManager;

    public ConfirmEmailModule(IdentityUserManager userManager) : base("confirmEmail")
    _userManager = userManager;
    Get["/", true] = async (x, ct) =>
    var validateAttempt = this.Bind<ValidateEmail>();
    var code = HttpUtility.UrlDecode(validateAttempt.Code);
    var result = await _userManager.ConfirmEmailAsync(Guid.Parse(validateAttempt.UserId), code);

    if (result.Succeeded)
    ViewBag.ReturnUrl = validateAttempt.ReturnUrl;
    return View["EmailValidated"];

    ViewBag.Errors = result.Errors;
    return View["ErrorValidatingEmail"];

    Post["/{userId}", true] = async (x, ct) =>
    var userId = Guid.Parse(x.userId);
    string code = await _userManager.GenerateEmailConfirmationTokenAsync(userId);
    var baseUrl = Context.Request.Url.SiteBase;
    var encodedCode = HttpUtility.UrlEncode(code);

    var callbackUrl = $"{baseUrl}/confirmEmail?userid={userId}&code={encodedCode}";

    await _userManager.SendEmailAsync(userId,
    "Confirm your email address",
    "Please confirm your email address by clicking <a href=\"" + callbackUrl + "\">here</a>");

    return HttpStatusCode.OK;

    Using Postman to post a userId to the endpoint to send a confirmation URL created the following confimation code


    And the URL encoded version to send in the email link becomes


    Now after clicking the emailed link, and then URL Decoding the validation code the code that is used for verification becomes

    frsv1AuYKgDTxcomdt27b/xLiGbzg/pv1k9e6X91B8enQUOIQn4sQ6w/vyZZ4QmIqHVHqMtuFXwbtSJoXKByKkTf7pM1EAftRwwJ2z3BZ/g61NLAhJQ5f8y8NcS b1vR /4Cs yni5GiNElTqqtZVj99c1SY J7Zsp Ke/YjkVU3Q75eoghFWlZaCnyUAr29

    Where all '+' chars in the original code have been replaced with spaces. Therefore there is an issue with directly URL encoding the Base64 string into a percent-encoded URL safe string. Hoever the wikipedia article on Base64 states that there is a URL safe variant of Base64, which does not use the percent encoding. A solution to creating URL safe Base64 string has been provided on Stack Overflow

    Using this sample, we can create a utility to make the Base64 codes URL safe, wihtout needing to generically URL encode a string.

    public static class Base64Utility
    static readonly char[] padding = { '=' };

    public static string UrlSafeEncode(this string base64String)
    return base64String.TrimEnd(padding).Replace('+', '-').Replace('/', '_');

    public static string UrlSafeDecode(this string urlSafeBase64String)
    string base64String = urlSafeBase64String.Replace('_', '/').Replace('-', '+');
    switch (urlSafeBase64String.Length % 4)
    case 2: base64String += "=="; break;
    case 3: base64String += "="; break;
    return base64String;

    By using this encode utility method, the encoded code that is URL safe for the activation link becomes


    and successfully decodes back to the original code generated by Asp.Net Identiy.

    * flickr photo by Gruenewiese86 https://flickr.com/photos/gruenewiese/27682943560 shared under a Creative Commons (BY-ND) license


    Post a Comment