使用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; })
问题原因与修复方案
核心问题点
- 全局默认认证Scheme配置错误:当前默认Scheme设为
OpenIdConnectDefaults.AuthenticationScheme,但用户登录后需通过Cookie维持会话,应将Cookie认证设为默认Scheme。 - SignInAsync Scheme不匹配:回调中
SignInAsync使用CookieAuthenticationDefaults.AuthenticationScheme,但配置的Cookie Scheme是自定义的"Identity.External",两者不一致导致会话Cookie无法正确关联。 - 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
相关产品推荐
相关产品推荐

