在 ASP.NET MVC 5 应用程序中启用 SSL 会导致 OpenIdConnectProtocolValidator 问题

Posted

技术标签:

【中文标题】在 ASP.NET MVC 5 应用程序中启用 SSL 会导致 OpenIdConnectProtocolValidator 问题【英文标题】:Enabling SSL in ASP.NET MVC 5 app results in OpenIdConnectProtocolValidator issue 【发布时间】:2015-06-12 17:03:47 【问题描述】:

我有一个针对 Azure Active Directory 进行身份验证的 ASP.NET MVC 5 应用程序。我想在整个应用程序上启用 SSL。因此利用全局过滤器如下:

public class FilterConfig

    /// <summary>
    /// Registers the global filters.
    /// </summary>
    /// <param name="filters">The filters.</param>
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    
        filters.Add(new RequireHttpsAttribute());
    

在此之后,我还将项目属性中的“启用 SSL”设置为 true。这给了我以下 SSL URL -> https://localhost:34567。我更新了项目,使其位于“项目 URL”中服务器下的“Web 选项卡”下的 IIS Express 路径中。但是在运行该站点时,我遇到了以下错误:

IDX10311:RequireNonce 为“真”(默认),但 validationContext.Nonce 为空。无法验证随机数。如果不需要检查 nonce,请将 OpenIdConnectProtocolValidator.RequireNonce 设置为 'false'。

我有授权。在网站上启用。我使用 Azure Active Directory。

安全码如下:

app.UseOpenIdConnectAuthentication(
            new OpenIdConnectAuthenticationOptions
            
                ClientId = clientId,
                Authority = authority,
                PostLogoutRedirectUri = postLogoutRedirectUri                    
            );

        app.UseWindowsAzureActiveDirectoryBearerAuthentication(
            new WindowsAzureActiveDirectoryBearerAuthenticationOptions
            
                Audience = audience,
                Tenant = tenant,      
            );

授权。正在从 web.config 读取值,如下所示:

<add key="ida:ClientId" value="<some_guid>" />
<add key="ida:Audience" value="https://localhost:34567/" />
<add key="ida:AADInstance" value="https://login.windows.net/0" />
<add key="ida:Tenant" value="microsoft.onmicrosoft.com" />
<add key="ida:PostLogoutRedirectUri" value="https://localhost:34567/" />

我尝试按照错误消息中的指示将 RequireNonce 设置为 false,如下所示:

ProtocolValidator = new OpenIdConnectProtocolValidator
                
                    RequireNonce = false
                

但这只是导致了一个无效的请求错误。

有人可以帮我理解这里的问题吗?在启用 SSL 之前一切正常。

【问题讨论】:

我想我明白了。该应用程序。 Azure AD 中的详细信息硬连线以依赖于原始 HTTP 终结点。一旦我验证了我的理论,就会更新这个。 我也收到了... 拜托,你修复了这个错误吗?我也有同样的情况。 在这个线程中检查我的答案:***.com/questions/39412570/… 【参考方案1】:

如果错误消息以 OICE_20004 开头或包含 IDX10311,您可以忽略异常。注意:风险自负。

Notifications = new OpenIdConnectAuthenticationNotifications()

    RedirectToIdentityProvider = (context) =>
    
        // Ensure the URI is picked up dynamically from the request;
        string appBaseUrl = context.Request.Scheme + "://" + context.Request.Host + context.Request.PathBase + context.Request.Uri.PathAndQuery;
        context.ProtocolMessage.RedirectUri = context.Request.Scheme + "://" + context.Request.Host + context.Request.PathBase + context.Request.Uri.PathAndQuery;
        context.ProtocolMessage.PostLogoutRedirectUri = appBaseUrl;
        return Task.FromResult(0);
    ,
    AuthenticationFailed = (context) =>
    
        if (context.Exception.Message.StartsWith("OICE_20004") || context.Exception.Message.Contains("IDX10311"))
        
            context.SkipToNextMiddleware();
            return Task.FromResult(0);
        
        return Task.FromResult(0);
    ,

【讨论】:

能否为您提供的解决方案添加更多描述? 在场景中为我工作:用户使用浏览器后退按钮导航到 SSO 身份验证页面。 你能添加一些描述吗? 我认为最好在跳到下一个中​​间件之前检查 context.OwinContext.Authentication.User.Identity.IsAuthenticated。【参考方案2】:

在 Azure 管理门户中,检查相应活动目录下的应用程序是否具有相同的登录 URL回复 URL

如果它们不一样,你会得到这个错误。

当您启用 SSL 时会发生这种情况,因为它仅将登录 URL 更改为 HTTPS URL,而回复 URL 保持相同的 HTTP URL。

编辑: 如果您想知道为什么会发生这种情况,请继续阅读,

当您尝试使用 https URL 访问您的应用程序时,它会在您的浏览器中设置一个具有唯一编号 (nonce) 的 cookie,并点击 Azure AD 进行身份验证。身份验证后,浏览器必须授予对该 cookie 的访问权限。但由于登录 URL 和回复 URL 不同,浏览器无法识别您的应用程序,也无法访问该 cookie,因此应用程序会抛出此错误。

【讨论】:

【参考方案3】:

即使在成功登录后,我也可以通过在我的 Web 应用程序上按几次后退按钮来重现此错误。 你能试试这两件事吗: 在下面的代码中:

app.UseOpenIdConnectAuthentication(
                new OpenIdConnectAuthenticationOptions
                
                    ClientId = mViewWebSite.ClientId,
                    Authority = mViewWebSite.Authority,
                    PostLogoutRedirectUri = mViewWebSite.PostLogoutRedirectUri
                );

添加协议验证器作为身份验证选项之一,如错误提示:

ProtocolValidator = new Microsoft.IdentityModel.Protocols.OpenIdConnectProtocolValidator()
                            RequireNonce = false
                        

或添加通知,通过此您可以捕获此错误并将其重定向到某个错误页面。我这样做是为了让它优雅。直到 Katana 人修复它。

Notifications = new OpenIdConnectAuthenticationNotifications
                        
                            AuthenticationFailed = context =>
                            
                                context.HandleResponse();
                                context.Response.Redirect("/Error.aspx?message=" + context.Exception.Message);
                                return Task.FromResult(0);
                            
                        ,

【讨论】:

使用这个很有意义,它对你有用吗?与github.com/IdentityServer/IdentityServer3/issues/542 中的“missxlian 于 2016 年 2 月 25 日发表评论”相比,您是否真的尝试过(也在这篇文章中建议)【参考方案4】:

我设法在 Global.asax 文件中使用以下方法解决此问题。至少这不会向客户端显示异常。我使用 ELMAH 来捕获异常。

protected void Application_Error(object sender, EventArgs args)
    
        var ex = Server.GetLastError();
        if (ex.Message.Contains("IDX10311:"))
        
            Server.ClearError();
            Response.Redirect("https://www.yoursitename.com");                 
        

【讨论】:

【参考方案5】:

好吧,最好看一下武士刀源代码,从中我发现异常类型是 OpenIdConnectProtocolInvalidNonceException 所以我这样处理它。

        if (n.Exception is OpenIdConnectProtocolInvalidNonceException &&
            n.OwinContext.Authentication.User.Identity.IsAuthenticated)
        
            n.SkipToNextMiddleware();
            return;
        

我在缓存页面和登录后单击后退按钮的用户的浏览器上弹出此异常。

【讨论】:

在哪些情况下可以在 AuthenticationFailed 通知上对用户进行身份验证(user.Identity.IsAuthenticated = true)? @TempoClick 登录后,点击返回按钮尝试返回上一页,某些登录参数不存在重新登录。【参考方案6】:

这里的问题很简单……我花了好几个小时才弄明白。 由于我在本地测试没有 https 并且在最初在 Azure AD 中创建我的应用程序时告诉你真相,因为我在测试期间不希望它是 https 我将其设为纯 http(replyUrl 的主页网址,注销所有爵士乐)

然后在这样做之后我遇到了无限循环问题,很多人都遇到了。所以然后我决定在我的本地模拟证书,是的,它摆脱了无限重定向,但随后又带来了另一个“IDX10311:RequireNonce is 'true'”

长话短说……让您的 AzureAD 应用程序在其所有端点中都使用 https。还有哇!

【讨论】:

或者您可以在 github.com/IdentityServer/IdentityServer3/issues/542 中尝试“missxlian 于 2016 年 2 月 25 日发表评论”(在这篇文章中也有建议)【参考方案7】:

@zb3b answer + @jonmeyer answer:

app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions

    ...
    Notifications = new OpenIdConnectAuthenticationNotifications()
    
        ...
        AuthenticationFailed = (context) =>
        
            if ((context.Exception is OpenIdConnectProtocolInvalidNonceException) &&
                (context.OwinContext.Authentication.User.Identity.IsAuthenticated))
            
                context.SkipToNextMiddleware();
                return Task.FromResult(0);
            

            return Task.FromResult(0);
        ,
        ...
    
);

【讨论】:

【参考方案8】:

添加我刚刚遇到的另一个案例:您连接的网络可能正在修改 html 内容。

一位客户致电提出问题:他无法解决此错误。那是一台他以前没有登录过的新笔记本电脑。在尝试了几种可能的解决方案大约一小时后,我决定检查他连接的网络。

事实证明,他连接到机场的网络,开放且不安全,并且没有使用 *** 服务(那里缺少一些 SETA)。我不确切知道谁在运营该网络或他们在做什么,但 Azure AD 服务一定检测到了某种类型的随机数篡改。

用户连接到可信网络的那一刻,问题就解决了。

【讨论】:

以上是关于在 ASP.NET MVC 5 应用程序中启用 SSL 会导致 OpenIdConnectProtocolValidator 问题的主要内容,如果未能解决你的问题,请参考以下文章

尝试在 ASP.Net MVC 网站中启用 CORS 时出错

具有捆绑和缩小功能的 ASP.NET MVC 4 应用程序,为啥在调试模式下启用缩小?

带有 ASP.NET MVC 的 jquery - 调用启用 ajax 的 Web 服务

asp.net mvc 应用Bundle(捆绑和微小)压缩技术 启用 BundleConfig 配置web.config

如何在 WEB API 的 ASP.NET MVC 控制器级别中启用 CORS? [复制]

在 ASP.NET 核心 MVC 项目上启用 CORS