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

.NET Core中Google OAuth2.0授权失败问题求助

Google OAuth授权失败与超时异常排查

问题描述

我正遵循Google的.NET API客户端库OAuth教程开发,测试控制器代码如下:

[HttpGet("listdrive")]
[GoogleScopedAuthorize(DriveService.ScopeConstants.DriveReadonly)]
public async Task<IActionResult> DriveFileList([FromServices] IGoogleAuthProvider auth)
{
    _logger.LogInformation("hello drive");
    var cred = await auth.GetCredentialAsync();

    var service = new DriveService(new BaseClientService.Initializer
    {
        HttpClientInitializer = cred
    });

    var files = await service.Files.List().ExecuteAsync();
    var fileNames = files.Files.Select(x => x.Name).ToList();

    _logger.LogInformation(fileNames.Count.ToString());

    return Ok();
}

已完成服务配置与依赖注入,Client ID和Secret在本地桌面应用中测试可用,配置代码如下:

services
        .AddAuthentication(o =>
        {
            // 强制挑战结果由Google OpenID Handler处理,无需额外添加登录用的AccountController
            o.DefaultChallengeScheme = GoogleOpenIdConnectDefaults.AuthenticationScheme;
            // 强制禁止结果由Google OpenID Handler处理,检查是否需要额外权限并自动增量授权
            o.DefaultForbidScheme = GoogleOpenIdConnectDefaults.AuthenticationScheme;
            // 默认处理所有其他场景的Scheme,用户认证后OAuth2令牌信息存储在Cookie中
            o.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        })
        .AddCookie()
        .AddGoogleOpenIdConnect(options =>
        {
            options.ClientId = "aaa";
            options.ClientSecret = "bbb";
        });

调用listdrive端点时出现授权失败,并抛出未处理异常,日志及堆栈信息如下:

[INFORMATION] 2024-02-06T00:07:16.5650763-04:00 [0HN16P1V10T97:00000003] - Authorization failed. These requirements were not met:
2024-02-06T04:07:16.565674114Z DenyAnonymousAuthorizationRequirement: Requires an authenticated user.
2024-02-06T04:07:16.565679663Z Google.Apis.Auth.AspNetCore3.GoogleScopedRequirement
[ERROR] 2024-02-06T00:07:56.4350328-04:00 [0HN16P1V10T86:00000002] - Connection id "0HN16P1V10T86", Request id "0HN16P1V10T86:00000002": An unhandled exception was thrown by the application.
System.InvalidOperationException: IDX20803: Unable to obtain configuration from: '[PII is hidden. For more details, see https://aka.ms/IdentityModel/PII.]'.
2024-02-06T04:07:56.436839985Z  ---&gt; System.IO.IOException: IDX20804: Unable to retrieve document from: '[PII is hidden. For more details, see https://aka.ms/IdentityModel/PII.]'.
2024-02-06T04:07:56.436844239Z  ---&gt; System.Threading.Tasks.TaskCanceledException: The request was canceled due to the configured HttpClient.Timeout of 60 seconds elapsing.
2024-02-06T04:07:56.436860190Z  ---&gt; System.TimeoutException: A task was canceled.
2024-02-06T04:07:56.436863714Z  ---&gt; System.Threading.Tasks.TaskCanceledException: A task was canceled.
2024-02-06T04:07:56.436866736Z    at System.Threading.Tasks.TaskCompletionSourceWithCancellation`1.WaitWithCancellationAsync(CancellationToken cancellationToken)
2024-02-06T04:07:56.436869650Z    at System.Net.Http.HttpConnectionPool.HttpConnectionWaiter`1.WaitForConnectionAsync(Boolean async, CancellationToken requestCancellationToken)
   at System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken)
2024-02-06T04:07:56.436875868Z    at System.Net.Http.DiagnosticsHandler.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.HttpClient.&lt;SendAsync&gt;g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)
   --- End of inner exception stack trace ---
2024-02-06T04:07:56.436890225Z    --- End of inner exception stack trace ---
   at System.Net.Http.HttpClient.HandleFailure(Exception e, Boolean telemetryStarted, HttpResponseMessage response, CancellationTokenSource cts, CancellationToken cancellationToken, CancellationTokenSource pendingRequestsCts)
   at System.Net.Http.HttpClient.&lt;SendAsync&gt;g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)
   at Microsoft.IdentityModel.Protocols.HttpDocumentRetriever.GetDocumentAsync(String address, CancellationToken cancel)
2024-02-06T04:07:56.436904982Z    --- End of inner exception stack trace ---
2024-02-06T04:07:56.436908002Z    at Microsoft.IdentityModel.Protocols.HttpDocumentRetriever.GetDocumentAsync(String address, CancellationToken cancel)
   at Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectConfigurationRetriever.GetAsync(String address, IDocumentRetriever retriever, CancellationToken cancel)
   at Microsoft.IdentityModel.Protocols.ConfigurationManager`1.GetConfigurationAsync(CancellationToken cancel)
2024-02-06T04:07:56.436917553Z    --- End of inner exception stack trace ---
   at Microsoft.IdentityModel.Protocols.ConfigurationManager`1.GetConfigurationAsync(CancellationToken cancel)
   at Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler.HandleChallengeAsyncInternal(AuthenticationProperties properties)
   at Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler.HandleChallengeAsync(AuthenticationProperties properties)
2024-02-06T04:07:56.436946952Z    at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.ChallengeAsync(AuthenticationProperties properties)
   at Microsoft.AspNetCore.Authentication.AuthenticationService.ChallengeAsync(HttpContext context, String scheme, AuthenticationProperties properties)
2024-02-06T04:07:56.436954263Z    at Microsoft.AspNetCore.Authorization.Policy.AuthorizationMiddlewareResultHandler.&lt;&gt;c__DisplayClass0_0.&lt;&lt;HandleAsync&gt;g__Handle|0&gt;d.MoveNext()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
2024-02-06T04:07:56.436963512Z    at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
2024-02-06T04:07:56.436973409Z    at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)

排查与解决步骤

1. 解决网络超时问题

异常核心是请求Google的OpenID配置文档超时,导致无法获取认证配置:

  • 检查开发/服务器环境是否能访问Google OpenID配置端点,可通过curl或浏览器直接访问测试连通性
  • 内网环境需配置代理,在AddGoogleOpenIdConnect中指定HttpClient代理:
    .AddGoogleOpenIdConnect(options =>
    {
        options.ClientId = "aaa";
        options.ClientSecret = "bbb";
        options.BackchannelHttpHandler = new HttpClientHandler
        {
            Proxy = new WebProxy("http://你的代理地址:端口"),
            UseProxy = true
        };
    });
    
  • 延长Backchannel超时时间:
    options.BackchannelTimeout = TimeSpan.FromMinutes(2);
    

2. 启用PII查看详细错误信息

开启PII显示可获取具体无法访问的URL,定位问题更精准:
在Program.cs中添加:

Microsoft.IdentityModel.Logging.IdentityModelEventSource.ShowPII = true;

重启应用后,异常信息会显示完整的配置请求URL。

3. 验证认证中间件配置

  • 确保Program.cs中已添加app.UseAuthentication()和app.UseAuthorization(),且顺序为先认证后授权
  • 检查Google Cloud控制台中,OAuth客户端类型为Web应用(桌面应用Client ID不适用于Web场景)
  • 确认OAuth客户端的授权重定向URI已正确配置为应用回调地址(默认路径为/signin-google)

4. 处理授权失败问题

授权失败提示未认证用户和缺少Drive权限,需做以下检查:

  • 确保访问listdrive端点前,用户已完成Google登录流程(网络正常时应用会自动跳转登录页)
  • 确认GoogleScopedAuthorize的Scope值正确,DriveService.ScopeConstants.DriveReadonly对应https://www.googleapis.com/auth/drive.readonly
  • 可在AddGoogleOpenIdConnect中预先添加该Scope,避免增量授权问题:
    options.Scope.Add(DriveService.ScopeConstants.DriveReadonly);
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 17:52:02