For those folks who have read the replies (above) and are scratching their heads, I've thought I'd step through a solution.
I used the code from jmichas (see above) which worked "out of the box" in a .net.core project.
https://gist.github.com/jmichas/dab35d9b8e916eae8936322465d76b66#file-rfc6238authenticationservice-cs
I was using the default email token provider that returns a URL. There are lots of tuts out there advocating this method, but its main drawback is that it create an orphaned browser window. It also doesn't play well with a PWA work flow.
Step one, add your new classes from the link above. There was already a directory called TokenProvider in my project, so I created them in there.
- FourDigitTokenProvider.cs
- CustomRfc6238AuthenticationService.cs
Copy across the code from the url (above)
Step two, find your startup.cs file and I commented out the existing provider
// options.Tokens.EmailConfirmationTokenProvider = "emailconf";
// .AddTokenProvider<EmailConfirmationTokenProvider<ApplicationUser>>("emailconf")
And added the new ones...
options.Tokens.ChangePhoneNumberTokenProvider = FourDigitTokenProvider.FourDigitPhone;
options.Tokens.EmailConfirmationTokenProvider = FourDigitTokenProvider.FourDigitEmail;
.AddTokenProvider<FourDigitTokenProvider>(FourDigitTokenProvider.FourDigitEmail)
.AddTokenProvider<FourDigitTokenProvider>(FourDigitTokenProvider.FourDigitPhone)
Build and check it compiles.
Step three, I was using the default MVC controller to handle the validation. We don't really need this any more so I just created a new endpoint to handle the validation from my site. Something like this:
[Produces("application/json")]
[HttpGet]
[Route("validateemailtoken/{token}/{email}")]
public async Task<IActionResult> ValidateEmailToken(string token, string email)
{
var user = await _userManager.FindByEmailAsync(email);
if (user != null)
{
if (user.EmailConfirmed)
{
return Ok(false);
}
var result = await _userManager.ConfirmEmailAsync(user, token);
if (result.Succeeded)
{
user.IsEnabled = true;
await _userManager.UpdateAsync(user);
return Ok(result.Succeeded);
} else
{
return Ok(false);
}
}
return BadRequest();
}
Step four, Ok, your user now will get an email with a four digit code, so you'll need your front end to input that code into your site (where they have been waiting for the email).
Grab the four digits and send it to your token server, so something like this...
GET http://localhost:xxxx/api/account/validateemailtoken/xxxx/[email protected]
It will return true if the user has been validated. You can log them in from there.
I hope all this helps.