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

在ASP.NET Core中使用Giraffe实现GitHub OAuth流程时出现重定向循环

解决Giraffe中GitHub OAuth的双重API调用与重定向循环问题

我明白你在Giraffe里搭建GitHub OAuth测试应用时遇到了两个棘手的问题:触发OnCreatingTicket事件时会两次调用https://api.github.com/user,而且回调路径/signin-github处理后会莫名重定向到/login形成循环,更奇怪的是重定向好像发生在Giraffe路由处理之前,日志里只看到/login的调用记录。我来帮你一步步拆解问题并给出解决办法:

一、双重调用api.github.com/user的根源

ASP.NET Core的GitHub认证中间件默认会在两个环节调用用户信息接口:

  • 当你调用challenge "GitHub"发起认证请求时,中间件拿到access token后,会自动调用一次api.github.com/user来填充ClaimsPrincipal;
  • 如果你在OnCreatingTicket事件里又手动写了调用这个接口的代码(比如想获取更多用户数据),就会导致重复调用。

解决思路:

  • 如果你只需要基础的用户信息,直接删掉OnCreatingTicket里手动调用接口的代码就行,中间件已经帮你搞定了;
  • 要是需要额外字段,直接用中间件已经获取到的context.User来提取,或者用context.AccessToken调用一次接口就够了,别重复触发请求。

二、/signin-github回调后重定向循环的排查与解决

你说/signin-github并不要求认证,但还是被重定向到/login,而且重定向在路由处理前就发生了,这大概率是认证中间件的配置顺序或者路由匹配逻辑出了问题,咱们一步步来修正:

可能的原因

  1. 中间件顺序错了:如果UseAuthentication放在了UseGiraffe之后,回调请求进来时,路由还没处理就先触发了认证检查,这时候OAuth的临时状态还没处理完,就会被判定为未认证,进而重定向到/login;
  2. 路由匹配优先级不对:你的路由定义里,mustBeLoggedIn包裹的是/api,但如果/signin-github的路由没被优先匹配到,请求可能落到404或者被错误的认证拦截;
  3. 回调路径配置与路由不匹配:虽然你设置了options.CallbackPath <- new PathString("/signin-github"),但如果路由里的/signin-github处理逻辑没正确绑定,中间件处理完回调后找不到对应的处理程序,就会触发默认重定向。

具体解决步骤

  1. 调整中间件加载顺序:一定要把UseAuthentication和UseAuthorization放在UseGiraffe前面,这样回调请求进来时,认证中间件先处理完OAuth流程,再交给Giraffe路由:
app.UseAuthentication()
   .UseAuthorization()
   .UseGiraffe(webApp)
  1. 修正路由匹配顺序:把不需要认证的路由(比如/signin-github)放在认证拦截逻辑的前面,确保请求能被优先匹配到:
let webApp = 
    logRequest >> 
    choose [ 
        GET >> choose [ 
            route "/" >> indexHandler "world" 
            route "/login" >> loginHandler 
            route "/signin-github" >> signinHandler 
        ]
        mustBeLoggedIn >> GET >> choose [ 
            route "/api" >> indexHandler "authenticated world" 
        ]
        setStatusCode 404 >> text "Not Found" 
    ]

这样/signin-github请求就不会被mustBeLoggedIn的拦截逻辑影响了。

  1. 简化回调处理逻辑:其实GitHub认证中间件会自动处理CallbackPath对应的请求,你不需要自己写signinHandler,只要确保注册中间件时配置正确就行:
services.AddAuthentication(options =>
    {
        options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = GitHubDefaults.AuthenticationScheme;
    })
    .AddCookie()
    .AddGitHub(options =>
    {
        options.ClientId = "你的ClientId";
        options.ClientSecret = "你的ClientSecret";
        options.CallbackPath = new PathString("/signin-github");
        // 自定义OnCreatingTicket时,避免重复调用用户接口
        options.Events = new OAuthEvents
        {
            OnCreatingTicket = async context =>
            {
                // 直接用context.User获取中间件已拿到的用户信息
                let userName = context.User.GetProperty("login").GetString();
                // 如果需要额外数据,用AccessToken调用一次即可
                let httpClient = new HttpClient();
                httpClient.DefaultRequestHeaders.Authorization = 
                    new AuthenticationHeaderValue("Bearer", context.AccessToken);
                let response = await httpClient.GetAsync("https://api.github.com/user/emails");
                response.EnsureSuccessStatusCode();
                let emails = await response.Content.ReadFromJsonAsync<JsonElement>();
                // 处理额外数据...
            }
        };
    });
  1. 检查Cookie认证配置:确保Cookie认证中间件配置正确,回调完成后能生成有效的认证Cookie,这样后续访问/api时就不会被重定向到/login了。

按照这些步骤调整后,应该就能解决重定向循环和双重API调用的问题了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 10:18:22