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

.NET 8 Web应用中如何重写signin-google端点获取Google访问令牌

如何在.NET 8中自定义Google外部登录回调逻辑(替代默认/signin-google端点)

默认情况下,ASP.NET Core OAuth中间件会优先处理Google登录的/signin-google回调端点,直接用控制器路由覆盖这个端点无效,暴力映射端点又会破坏其他登录流程,这里提供两种合规的解决方案:

方案一:利用OAuth事件拦截令牌(推荐)

无需修改默认回调端点,通过中间件的事件机制在回调流程中插入自定义逻辑,获取授权码或访问令牌:

在配置Google认证时添加事件处理:

builder.Services.AddAuthentication()
    .AddGoogle(options =>
    {
        options.ClientId = builder.Configuration["Authentication:Google:ClientId"];
        options.ClientSecret = builder.Configuration["Authentication:Google:ClientSecret"];
        
        options.Events = new OAuthEvents
        {
            // 在令牌接收阶段获取授权码
            OnTokenReceived = async context =>
            {
                var authorizationCode = context.TokenEndpointRequest.Code;
                // 调用业务服务保存授权码
                await context.HttpContext.RequestServices
                    .GetRequiredService<ILoginService>()
                    .RegisterTokenAsync(context.Principal?.Identity?.Name, authorizationCode);
            },
            // 在用户票据创建阶段,可获取完整用户身份和访问令牌
            OnCreatingTicket = async context =>
            {
                var userName = context.Principal.Identity.Name;
                var accessToken = context.AccessToken;
                // 保存访问令牌到业务系统
                await context.HttpContext.RequestServices
                    .GetRequiredService<ILoginService>()
                    .RegisterTokenAsync(userName, accessToken);
            }
        };
    });

这种方式复用中间件默认流程,不会影响其他登录方式,同时能轻松获取所需令牌信息。

方案二:自定义回调端点

如果需要完全掌控回调流程,可以修改Google认证的CallbackPath,将回调指向自定义控制器端点:

1. 修改Google认证配置

builder.Services.AddAuthentication()
    .AddGoogle(options =>
    {
        options.ClientId = builder.Configuration["Authentication:Google:ClientId"];
        options.ClientSecret = builder.Configuration["Authentication:Google:ClientSecret"];
        // 将回调路径改为自定义端点
        options.CallbackPath = "/account/google-callback";
    });

2. 实现自定义回调控制器方法

public class AccountController : Controller
{
    private readonly ILoginService _loginService;
    private readonly IAuthenticationService _authService;

    public AccountController(ILoginService loginService, IAuthenticationService authService)
    {
        _loginService = loginService;
        _authService = authService;
    }

    [HttpGet("/account/google-callback")]
    public async Task<IActionResult> GoogleCallback()
    {
        // 让认证中间件处理回调请求,生成用户身份
        var authResult = await _authService.AuthenticateAsync(HttpContext, GoogleDefaults.AuthenticationScheme);

        if (authResult.Succeeded)
        {
            // 从认证属性中提取授权码和访问令牌
            var authProps = authResult.Properties;
            var code = authProps.GetTokenValue("code");
            var accessToken = authProps.GetTokenValue("access_token");

            // 保存令牌到业务系统
            await _loginService.RegisterTokenAsync(authResult.Principal.Identity.Name, code);

            // 完成用户登录
            await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, authResult.Principal, authProps);
            
            return RedirectToAction("Index", "Home");
        }

        return RedirectToAction("Login", "Account");
    }
}

为什么之前的方法无效?

  • 直接用[Route("signin-google")]标注控制器方法无效:OAuth中间件会在端点路由之前匹配CallbackPath对应的请求,控制器路由根本不会被命中。
  • 暴力映射端点会覆盖中间件的处理逻辑,导致依赖中间件的其他登录方式(如用户名密码登录)失效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 09:47:03