You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core 7.0中ConfirmEmailAsync返回无效令牌问题排查

问题原因及解决方案

核心原因

你遇到的问题是生成邮箱确认令牌后修改了用户的SecurityStamp,导致验证时令牌与当前用户的SecurityStamp不匹配。

ASP.NET Core Identity生成邮箱确认令牌时,会结合用户的SecurityStamp(用户安全戳)进行加密。而你在生成令牌后,执行了两个会修改用户数据的操作:

  • SetTwoFactorEnabledAsync(user, true):启用双因素认证会更新用户的SecurityStamp
  • AddToRoleAsync(user, role.Name):给用户添加角色也会触发SecurityStamp更新

这两个操作会改变用户的SecurityStamp,而验证令牌时,Identity会用当前用户的SecurityStamp去解密令牌,自然就会提示"Invalid token"。

解决方案

调整操作顺序,先完成所有用户属性修改和角色分配,再生成邮箱确认令牌。修改注册代码如下:

if (result.Succeeded)
{
    _logger.LogInformation("User created a new account with password.");

    var userId = await _userManager.GetUserIdAsync(user);

    // 先执行所有会修改用户的操作
    var setTwoFactorResult = await _userManager.SetTwoFactorEnabledAsync(user, true);
    if (!setTwoFactorResult.Succeeded)
    {
        _logger.LogInformation("Two factor authentication failed to set.");
    }

    var addToRoleResult = await _userManager.AddToRoleAsync(user, role.Name);
    if (!addToRoleResult.Succeeded) // 修正原代码判断逻辑错误
    {
        _logger.LogInformation("Role not assigned to user");
    }

    // 最后生成邮箱确认令牌
    var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
    code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));

    // 后续生成回调URL、发送邮件的代码保持不变
    var callbackUrl = Url.Page(
        "/Account/ConfirmEmail",
        pageHandler: null,
        values: new { area = "Identity", userId = user.Id, code = code, returnUrl = returnUrl },
        protocol: Request.Scheme);

    var confirmationEmail = new EmailInfo()
    {
        EmailTo = Input.Email,
        Subject = "Yellow Fever Account Confirmation Email",
        Body = $"Please use the following code to confirm your account <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>"
    };

    await _emailService.SendEmailAsync(confirmationEmail);

    return RedirectToPage("RegisterConfirmation", new { email = Input.Email, returnUrl = returnUrl });
}

注:原代码中addToRoleResult.Succeeded的判断逻辑写反了,应该是添加角色失败时才记录日志,上述代码已修正该问题。

内容的提问来源于stack exchange,提问作者user20408154

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 07:49:57