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

使用Google Auth API认证用户时SignInAsync调用异常问题排查

问题描述

在Asp.Net MVC应用中实现Google用户认证时,登录流程可正常跳转至Google页面并完成登录,但回调方法中User.Identity.IsAuthenticated显示为true,重定向到首页加载_LoginPartial时,User.Identity却为null。

相关代码如下:

_LoginPartial.cshtml 代码

<ul class="navbar-nav">
  @if (User?.Identity?.IsAuthenticated ?? false)
  {
    <li class="nav-item">
        <span class="navbar-text text-dark">Signed in as @User.Identity.Name!</span>
    </li>
  }
  else
    {
        <a class="nav-link text-dark" asp-controller="Account" asp-action="SignInWithGoogle">SignInWithGoogle</a>
    </li>
    }
</ul>

GoogleCallback 回调方法

[HttpGet]
public async Task<IActionResult> GoogleCallback()
{
    var result = await _httpContextAccessor!.HttpContext!.AuthenticateAsync("Google");
    if (result.Succeeded && result.Principal != null)
    {
        var claimsPrincipal = new ClaimsPrincipal(result.Principal);

        await _httpContextAccessor!.HttpContext!.SignInAsync(
            CookieAuthenticationDefaults.AuthenticationScheme,
            claimsPrincipal,
            new AuthenticationProperties { 
                IsPersistent = true,
                AllowRefresh = true,
                ExpiresUtc = DateTimeOffset.UtcNow.AddMinutes(10),
            });

        HttpContext.User = claimsPrincipal;

        Console.WriteLine(User?.Identity?.IsAuthenticated); // Identity set here
    }

    return RedirectToAction("Index", "Home");
}

认证配置代码

builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
    .AddCookie("Identity.External", options =>
    {
        options.Cookie.IsEssential = true;
        options.Cookie.Name = "Identity.External";
        options.Cookie.SameSite = SameSiteMode.Lax;
    })    
    .AddGoogle(options =>
    {
        options.ClientId = id;
        options.ClientSecret = secret;
        options.SignInScheme = IdentityConstants.ExternalScheme;
    })
问题原因与修复方案

核心问题点

  1. 全局默认认证Scheme配置错误:当前默认Scheme设为OpenIdConnectDefaults.AuthenticationScheme,但用户登录后需通过Cookie维持会话,应将Cookie认证设为默认Scheme。
  2. SignInAsync Scheme不匹配:回调中SignInAsync使用CookieAuthenticationDefaults.AuthenticationScheme,但配置的Cookie Scheme是自定义的"Identity.External",两者不一致导致会话Cookie无法正确关联。
  3. Google认证SignInScheme设置错误:options.SignInScheme指向了ASP.NET Identity专属的IdentityConstants.ExternalScheme,但未使用Identity框架,应指向自定义的Cookie Scheme。

修复步骤

步骤1:修正认证配置

将默认认证Scheme改为自定义Cookie Scheme,同时统一Google的SignInScheme配置:

// 自定义Cookie Scheme作为默认认证Scheme
builder.Services.AddAuthentication("Identity.External")
    .AddCookie("Identity.External", options =>
    {
        options.Cookie.IsEssential = true;
        options.Cookie.Name = "Identity.External";
        options.Cookie.SameSite = SameSiteMode.Lax;
        // 配置未认证请求的跳转路径
        options.LoginPath = "/Account/SignInWithGoogle";
    })    
    .AddGoogle(options =>
    {
        options.ClientId = id;
        options.ClientSecret = secret;
        // 指向自定义的Cookie Scheme
        options.SignInScheme = "Identity.External";
    });

步骤2:修正回调方法逻辑

使用与配置一致的Cookie Scheme调用SignInAsync,同时简化认证验证逻辑:

[HttpGet]
public async Task<IActionResult> GoogleCallback()
{
    var result = await HttpContext.AuthenticateAsync("Identity.External");
    if (result.Succeeded && result.Principal != null)
    {
        await HttpContext.SignInAsync(
            "Identity.External",
            result.Principal,
            new AuthenticationProperties { 
                IsPersistent = true,
                AllowRefresh = true,
                ExpiresUtc = DateTimeOffset.UtcNow.AddMinutes(10),
            });
    }

    return RedirectToAction("Index", "Home");
}

步骤3:(可选)使用默认Cookie Scheme简化配置

若无需自定义Cookie名称,可直接使用默认Scheme,配置更简洁:

builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddCookie(options =>
    {
        options.Cookie.IsEssential = true;
        options.Cookie.SameSite = SameSiteMode.Lax;
        options.LoginPath = "/Account/SignInWithGoogle";
    })    
    .AddGoogle(options =>
    {
        options.ClientId = id;
        options.ClientSecret = secret;
        options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    });

对应回调方法中,SignInAsync和AuthenticateAsync均使用CookieAuthenticationDefaults.AuthenticationScheme即可。

额外注意事项

  • 无需手动设置HttpContext.User = claimsPrincipal,SignInAsync会自动处理后续请求的用户身份
  • 确保Program.cs中已添加app.UseAuthentication()和app.UseAuthorization(),且UseAuthentication需在UseAuthorization之前执行

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 20:46:34