ASP.NET Core与Blazor应用中Google认证的OAuth状态缺失/无效问题
问题核心原因
你当前的配置存在流程不兼容问题:前端使用的是Google Identity Services (GSI) 的POST式登录流程(通过data-login_uri直接提交凭证),但后端AddGoogle()配置的是ASP.NET Core默认的传统OAuth授权码流程(跳转Google授权页后回调到signin-google)。两种流程的state验证逻辑不匹配,导致出现AuthenticationFailureException: The OAuth state was missing or invalid错误。
解决方案
以下提供两种适配方案,根据你的业务需求选择:
方案一:切换到ASP.NET Core传统OAuth授权码流程
该方案符合ASP.NET Core Google认证的原生设计,无需自定义凭证处理逻辑:
修改API端,添加Google登录触发端点
在API中新增认证控制器,提供触发Google授权跳转的接口:[ApiController] [Route("api/auth")] public class AuthController : ControllerBase { [HttpGet("login-google")] public IActionResult LoginGoogle() { // 设置回调地址,需与Google控制台配置一致 var redirectUrl = Url.Action("ExternalLoginCallback", "Auth"); var properties = new AuthenticationProperties { RedirectUri = redirectUrl }; return Challenge(properties, GoogleDefaults.AuthenticationScheme); } [HttpGet("external-login-callback")] public async Task<IActionResult> ExternalLoginCallback() { // 验证Google回调的认证结果 var result = await HttpContext.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationScheme); if (!result.Succeeded) { return BadRequest("Google认证失败"); } // 此处可扩展:创建/关联本地用户、生成JWT令牌等 var userClaims = result.Principal.Claims; // 重定向到Blazor前端的登录成功页面 return Redirect("http://localhost:xxxx/account/success"); } }修改前端,替换GSI按钮为跳转链接
删除原有的GSI脚本和按钮代码,改用指向API登录端点的链接:<a href="http://localhost:5083/api/auth/login-google" class="flex items-center justify-center w-full px-4 py-2 border border-gray-300 rounded-lg hover:bg-gray-50"> <img src="https://developers.google.com/identity/images/g-logo.png" class="w-5 h-5 mr-2" /> 使用Google登录 </a>更新Google控制台配置
将重定向URI修改为API的回调地址:http://localhost:5083/api/auth/external-login-callback
方案二:自定义端点适配GSI的POST登录流程
如果希望保留GSI按钮的交互体验,需自定义API端点处理GSI提交的id_token:
保留前端GSI代码,修改login_uri
将data-login_uri指向自定义的API端点:<div id="g_id_onload" data-client_id="xxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com" data-login_uri="http://localhost:5083/api/auth/google-signin" data-auto_prompt="false" class="rounded-xl"> </div>API端添加GSI凭证验证端点
新增端点验证Google的id_token并完成登录逻辑:[ApiController] [Route("api/auth")] public class AuthController : ControllerBase { private readonly IConfiguration _config; public AuthController(IConfiguration config) { _config = config; } [HttpPost("google-signin")] public async Task<IActionResult> GoogleSignIn([FromForm] string credential) { // 验证Google id_token的有效性 var validationSettings = new GoogleJsonWebSignature.ValidationSettings { Audience = new List<string> { _config["Authentication:Google:ClientId"] } }; try { var payload = await GoogleJsonWebSignature.ValidateAsync(credential, validationSettings); // 构建用户身份凭证 var claims = new List<Claim> { new Claim(ClaimTypes.Email, payload.Email), new Claim(ClaimTypes.Name, payload.Name), new Claim("Picture", payload.Picture) }; var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme); await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(identity)); // 重定向到前端登录成功页面 return Redirect("http://localhost:xxxx/account/success"); } catch (InvalidJwtException) { return BadRequest("无效的Google登录凭证"); } } }补充跨域与Cookie配置
由于前后端跨域,需在API中配置CORS并调整Cookie策略:// 添加CORS服务 builder.Services.AddCors(options => { options.AddPolicy("AllowBlazor", policy => { policy.WithOrigins("http://localhost:xxxx") // Blazor前端地址 .AllowAnyHeader() .AllowAnyMethod() .AllowCredentials(); // 允许携带Cookie }); }); // 调整Cookie认证配置 builder.Services.AddAuthentication(options => { options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; }) .AddCookie(options => { options.Cookie.SameSite = SameSiteMode.Lax; options.Cookie.Path = "/"; options.Cookie.HttpOnly = true; options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest; }) .AddGoogle(options => { options.ClientId = _config["Authentication:Google:ClientId"] ?? string.Empty; options.ClientSecret = _config["Authentication:Google:ClientSecret"] ?? string.Empty; }); // 在请求管道中启用CORS(需在UseAuthentication之前) app.UseCors("AllowBlazor");更新Google控制台配置
- 授权来源添加Blazor前端地址:
http://localhost:xxxx - 重定向URI设置为自定义端点:
http://localhost:5083/api/auth/google-signin
- 授权来源添加Blazor前端地址:
内容的提问来源于stack exchange,提问作者Jelles

