.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 ---> 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 ---> System.Threading.Tasks.TaskCanceledException: The request was canceled due to the configured HttpClient.Timeout of 60 seconds elapsing. 2024-02-06T04:07:56.436860190Z ---> System.TimeoutException: A task was canceled. 2024-02-06T04:07:56.436863714Z ---> 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.<SendAsync>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.<SendAsync>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.<>c__DisplayClass0_0.<<HandleAsync>g__Handle|0>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
相关产品推荐
相关产品推荐

