.NET中OWIN中间件无法触发认证服务器登录界面问题排查
.NET应用Azure OpenID Connect认证异常排查
问题背景
我有一个基于.NET的应用,使用OpenID Connect认证(Azure作为认证服务器),此前一直运行正常,最近突然出现异常。
错误信息
当前运行时弹出如下错误:
堆栈跟踪
[IOException: IDX20807: Unable to retrieve document from: 'System.String'. HttpResponseMessage: 'System.Net.Http.HttpResponseMessage', HttpResponseMessage.Content: 'System.String'.] Microsoft.IdentityModel.Protocols.<GetDocumentAsync>d__16.MoveNext() +1152 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() +32 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +62 Microsoft.IdentityModel.Protocols.OpenIdConnect.<GetAsync>d__3.MoveNext() +391 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() +32 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +62 Microsoft.IdentityModel.Protocols.<GetConfigurationAsync>d__24.MoveNext() +958 [InvalidOperationException: IDX20803: Unable to obtain configuration from: 'System.String'.] Microsoft.IdentityModel.Protocols.<GetConfigurationAsync>d__24.MoveNext() +1699 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() +32 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +62 Microsoft.Owin.Security.OpenIdConnect.<ApplyResponseChallengeAsync>d__10.MoveNext() +565 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() +32 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +62 Microsoft.Owin.Security.Infrastructure.<ApplyResponseCoreAsync>d__40.MoveNext() +349 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() +32 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +62 Microsoft.Owin.Security.Infrastructure.<ApplyResponseAsync>d__39.MoveNext() +447 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() +32 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +62 Microsoft.Owin.Security.Infrastructure.<TeardownAsync>d__34.MoveNext() +196 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() +32 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +62 Microsoft.Owin.Security.Infrastructure.<Invoke>d__5.MoveNext() +929 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() +32 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +62 Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.<RunApp>d__7.MoveNext() +197 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() +32 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +62 Microsoft.Owin.Security.Infrastructure.<Invoke>d__5.MoveNext() +735 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() +32 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +62 NSwag.AspNet.Owin.Middlewares.<Invoke>d__4.MoveNext() +881 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() +32 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +62 NSwag.AspNet.Owin.Middlewares.<Invoke>d__4.MoveNext() +809 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() +32 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +62 NSwag.AspNet.Owin.Middlewares.<Invoke>d__7.MoveNext() +830 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() +32 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +62 Microsoft.Owin.Mapping.<Invoke>d__3.MoveNext() +861 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() +32 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +62 Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.<RunApp>d__7.MoveNext() +197 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() +32 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +62 Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.<DoFinalWork>d__12.MoveNext() +192 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() +32 Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.StageAsyncResult.End(IAsyncResult ar) +118 System.Web.AsyncEventExecutionStep.InvokeEndHandler(IAsyncResult ar) +225 System.Web.AsyncEventExecutionStep.OnAsyncEventCompletion(IAsyncResult ar) +162
注:我确认应用此前可正常工作,且相关代码确实在执行。
相关配置代码
Startup.cs中的认证配置
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType); app.UseCookieAuthentication(new CookieAuthenticationOptions()); app.UseOpenIdConnectAuthentication( new OpenIdConnectAuthenticationOptions { // Sets the ClientId, authority, RedirectUri as obtained from web.config ClientId = clientId, Authority = authority, RedirectUri = redirectUri, // PostLogoutRedirectUri is the page that users will be redirected to after sign-out. In this case, it is using the home page PostLogoutRedirectUri = redirectUri, Scope = OpenIdConnectScope.OpenIdProfile, // ResponseType is set to request the code id_token - which contains basic information about the signed-in user ResponseType = OpenIdConnectResponseType.CodeIdToken, // OpenIdConnectAuthenticationNotifications configures OWIN to send notification of failed authentications to OnAuthenticationFailed method Notifications = new OpenIdConnectAuthenticationNotifications { AuthenticationFailed = OnAuthenticationFailed, } });
默认控制器触发登录的代码
public HttpStatusCodeResult SignIn() { if (!Request.IsAuthenticated) { HttpContext.GetOwinContext().Authentication.Challenge( new AuthenticationProperties { RedirectUri = MeshConfigSupport.LocalSettings.TryGetSetting<string>("RedirectUri").value,}, OpenIdConnectAuthenticationDefaults.AuthenticationType); } HttpStatusCodeResult statusCode = new HttpStatusCodeResult(HttpContext.GetOwinContext().Response.StatusCode); return statusCode; }
排查与解决方法
1. 验证配置参数正确性
- 检查
authority变量的实际值:确认web.config中的Authority配置格式正确,应为https://login.microsoftonline.com/{租户ID}或https://login.microsoftonline.com/{租户ID}/v2.0,租户ID不能缺失或错误 - 核对Azure AD应用注册中的
ClientId、RedirectUri是否与代码中完全一致,Redirect URI需严格匹配协议(http/https)、端口和路径
2. 排查网络访问问题
- 在应用所在服务器上直接访问Azure AD的OpenID配置端点(比如
https://login.microsoftonline.com/{租户ID}/v2.0/.well-known/openid-configuration),确认能正常返回JSON格式的配置内容 - 检查服务器防火墙、企业代理是否限制了对
login.microsoftonline.com的出站请求,必要时添加白名单或配置代理
3. 检查NuGet包兼容性
- 查看
Microsoft.Owin.Security.OpenIdConnect、Microsoft.IdentityModel.Protocols.OpenIdConnect等相关包的版本,是否存在版本冲突或已知bug - 尝试升级到最新稳定版,或回退到之前能正常运行的版本
4. 扩展认证失败通知获取详细错误
完善OnAuthenticationFailed方法,捕获更具体的异常信息:
private Task OnAuthenticationFailed(AuthenticationFailedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification) { notification.HandleResponse(); var errorMsg = Uri.EscapeDataString(notification.Exception.Message + (notification.Exception.InnerException != null ? " | " + notification.Exception.InnerException.Message : "")); notification.Response.Redirect("/Error?message=" + errorMsg); return Task.CompletedTask; }
通过这个方法可以获取到更底层的错误原因,比如SSL证书验证失败、请求超时等
5. 清除配置缓存
OpenID Connect配置默认会被缓存,尝试重启应用池或清理应用的本地缓存,避免旧缓存导致的配置读取问题
内容的提问来源于stack exchange,提问作者Diego
相关产品推荐
相关产品推荐

