Jones
Jones

Reputation: 217

Asp net Core ConfirmEmail not working

I want to setup a confirm email for new users.

[HttpGet]
    [AllowAnonymous]
    public async Task<IActionResult> ConfirmEmail(string userId, string code)
    {
        if (userId == null || code == null)
        {
            return RedirectToAction(nameof(HomeController.Index), "Home");
        }
        var user = await _userManager.FindByIdAsync(userId);
        if (user == null)
        {
            throw new ApplicationException($"Unable to load user with ID '{userId}'.");
        }
        var result = await _userManager.ConfirmEmailAsync(user, code);
        return View(result.Succeeded ? "ConfirmEmail" : "Error");
    }

So when debugging when the link is clicked the userId is ok but the "code" input parameter is null so

if (userId == null || code == null)

is true and then it executes

return RedirectToAction(nameof(HomeController.Index), "Home");

The email that is sent to the registered user is like this :

Please confirm your account by clicking this link: https://localhost:44314/Account/ConfirmEmail?userId=3ec7ac6a-3329-4821-a09b-aa4843598eaa&code=CfDJ8JouO%2BAfPaZIsebmFKKodcE1jEFscFSMcDTvnUPw88tqAKIh0%2BFV6X%2BWCF6fRBgprsymV37RsZsupPoRwCoj8tTT8CckBr0BP9se6DuBxd%2B8fDg2go2S0X9o%2FD9outoU7ShVJl3r3lM5yMXjevtJBoQha9g66ithx%2BhM4Dfskpzt79Imyad6BC0s8s53C7qGZhIx5Dh6DU2KXcVues8XxYQAAhFvzn%2BT49N3ze1%2BihB4Ciwxo5En6sT%2BmbaWvX9N2A%3D%3D'>link

Edit: the link contains & a m p;code instead of &code but it doesen't show in stack overflow

Literally no one has the same problem on the internet so I'm lost here. What am I doing wrong?

public static class UrlHelperExtensions
{
    public static string EmailConfirmationLink(this IUrlHelper urlHelper, string userId, string code, string scheme)
    {
        return urlHelper.Action(
            action: nameof(AccountController.ConfirmEmail),
            controller: "Account",
            values: new { userId, code },
            protocol: scheme);
    }

    public static string ResetPasswordCallbackLink(this IUrlHelper urlHelper, string userId, string code, string scheme)
    {
        return urlHelper.Action(
            action: nameof(AccountController.ResetPassword),
            controller: "Account",
            values: new { userId, code },
            protocol: scheme);
    }
}

Update: When I changed & a m p;code to "&code" in the link and pasted it in chrome it worked

Upvotes: 4

Views: 2732

Answers (2)

Norbert Norbertson
Norbert Norbertson

Reputation: 2210

As above this code:

HtmlEncoder.Default.Encode(link)

Is wrong. We are not encoding HTML here. We are encoding an url. One would think that therefore, we should be using url encoding. This:

HttpUtility.UrlEncode(link);

However, it appears that Url.Page is clever enough to encode the parameters automatically. Try the below code:

var callbackUrl = Url.Page(
            "/Account/ConfirmEmail",
            pageHandler: null,
            values: new { area = "Identity", userId = "12345", code = 
"567&9", returnUrl = "/index" },
            protocol: Request.Scheme);

The result is this:

https://localhost:44383/Identity/Account/ConfirmEmail?userId=12345&code=567%269&returnUrl=%2Findex

As you can see the ampersand in the "code" parameter is being encoded. So the encoding is not necessary and the answer by Jones above is correct.

Upvotes: 1

Jones
Jones

Reputation: 217

public static Task SendEmailConfirmationAsync(this IEmailSender emailSender, string email, string link)
    {
        return emailSender.SendEmailAsync(email, "Confirm your email",
            $"Please confirm your account by clicking this link: <a href='{HtmlEncoder.Default.Encode(link)}'>link</a>");
    }

The problem is here

HtmlEncoder.Default.Encode(link)

just remove it and it works

<a href='{link}'>link</a>

Upvotes: 6

Related Questions