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

ASP.NET Core与Blazor应用中Google认证的OAuth状态缺失/无效问题

解决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认证的原生设计,无需自定义凭证处理逻辑:

  1. 修改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");
        }
    }
    
  2. 修改前端,替换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>
    
  3. 更新Google控制台配置
    将重定向URI修改为API的回调地址:http://localhost:5083/api/auth/external-login-callback


方案二:自定义端点适配GSI的POST登录流程

如果希望保留GSI按钮的交互体验,需自定义API端点处理GSI提交的id_token:

  1. 保留前端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>
    
  2. 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登录凭证");
            }
        }
    }
    
  3. 补充跨域与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");
    
  4. 更新Google控制台配置

    • 授权来源添加Blazor前端地址:http://localhost:xxxx
    • 重定向URI设置为自定义端点:http://localhost:5083/api/auth/google-signin

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 00:27:08