ADFS令牌加密证书链验证失败

时间:2016-10-21 19:07:12

标签: c# asp.net-mvc validation certificate adfs

我有ASP.NET MVC网站,我配置为通过Active Directory联合身份验证服务进行身份验证。一切正常,直到我尝试启用令牌加密。像往常一样,我在IIS上创建了一个自签名证书,将其添加到我的Web服务器和ADFS服务器上的“受信任的根”权限,并运行应用程序以使其非常有效。

我的应用程序正确地将我重定向到ADFS服务页面以输入凭据。但是,当我提交登录名和密码时,我立即得到了{" An error occured"消息在同一登录页面上,但没有非常有用的详细信息部分:

Activity ID: 00000000-0000-0000-b039-0080010000e4
Relying party: [My relying party name]
Error time: Fri, 21 Oct 2016 18:48:24 GMT
Cookie: enabled
User agent string: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.59 Safari/537.36

之后我没有被重定向到我的网站,而且网络面板不包含任何请求。

但我发现,如果我将以下设置添加到我的网站的web.config中,它会再次开始工作:

<certificateValidation certificateValidationMode="None" />

因此,错误必须与我的证书是自签名的事实有关。但我已将它添加到Web服务器和ADFS服务器上的受信任的根权限(以及其他一些&#34;可疑的&#34;证书)。

是否有人知道可能缺少哪些内容?我可以做些什么来使我的测试环境使用自签名证书,同时验证证书链?

3 个答案:

答案 0 :(得分:0)

我使用api处理程序执行类似操作,该处理程序充当传递,并且必须询问证书。

可能有助于您进行问题排查的内容。

将证书验证回调设置为:

// validate server cert
ServicePointManager.ServerCertificateValidationCallback += ValidateServerCertificate;

然后在验证方法中,您可以询问链:

private static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
        {
            // default validation bool to false
            var isValid = false;

            // If the certificate is a valid, signed certificate, return true to short circuit any add'l processing.
            if (sslPolicyErrors == SslPolicyErrors.None)
            {
                return true;
            }
            else
            {
                // cast cert as v2 in order to expose thumbprint prop
                var requestCertificate = (X509Certificate2)certificate;

                // init string builder for creating a long log entry
                var logEntry = new StringBuilder();

                // capture initial info for the log entry
                logEntry.AppendFormat("Certificate Validation Error - SSL Policy Error: {0} - Cert Issuer: {1} - SubjectName: {2}",
                   sslPolicyErrors.ToString(),
                   requestCertificate.Issuer,
                   requestCertificate.SubjectName.Name);

                //init special builder for thumprint mismatches
                var thumbprintMismatches = new StringBuilder();

                // load valid certificate thumbs for comparison later
                var validThumbprints = new string[] { "thumbprint A", "thumbprint N" };

                // else if a cert name mismatch then assume api pass thru issue and verify thumb print
                if (sslPolicyErrors == SslPolicyErrors.RemoteCertificateNameMismatch) 
                {
                    // compare thumbprints
                    var hasMatch = validThumbprints.Contains(requestCertificate.Thumbprint, StringComparer.OrdinalIgnoreCase);

                    // if match found then we're valid so clear builder and set global valid bool to true
                    if (hasMatch)
                    {
                        thumbprintMismatches.Clear();
                        isValid = true;
                    }
                    // else thumbprint did not match so append to the builder
                    else
                    {
                        thumbprintMismatches.AppendFormat("|Thumbprint mismatch - Issuer: {0} - SubjectName: {1} - Thumbprint: {2}",
                             requestCertificate.Issuer,
                             requestCertificate.SubjectName.Name,
                             requestCertificate.Thumbprint);
                    }
                }
                // else if chain issue, then iterate over the chain and attempt find a matching thumbprint
                else if (sslPolicyErrors == SslPolicyErrors.RemoteCertificateChainErrors) //Root CA problem
                {
                    // check chain status and log
                    if (chain != null && chain.ChainStatus != null)
                    {
                        // check errors in chain and add to log entry
                        foreach (var chainStatus in chain.ChainStatus)
                        {
                            logEntry.AppendFormat("|Chain Status: {0} - {1}", chainStatus.Status.ToString(), chainStatus.StatusInformation.Trim());
                        }

                        // check for thumbprint mismatches
                        foreach (var chainElement in chain.ChainElements)
                        {
                            // compare thumbprints
                            var hasMatch = validThumbprints.Contains(chainElement.Certificate.Thumbprint, StringComparer.OrdinalIgnoreCase);

                            // if match found then we're valid so break, clear builder and set global valid bool to true
                            if (hasMatch)
                            {
                                thumbprintMismatches.Clear();
                                isValid = true;
                                break;
                            }
                            // else thumbprint did not match so append to the builder
                            else
                            {
                                thumbprintMismatches.AppendFormat("|Thumbprint mismatch - Issuer: {0} - SubjectName: {1} - Thumbprint: {2}",
                                     chainElement.Certificate.Issuer,
                                     chainElement.Certificate.SubjectName.Name,
                                     chainElement.Certificate.Thumbprint);
                            }
                        }
                    }
                }

                // if still invalid and thumbprint builder has items, then continue 
                if (!isValid && thumbprintMismatches != null && thumbprintMismatches.Length > 0)
                {
                    // append thumbprint entries to the logentry as well
                    logEntry.Append(thumbprintMismatches.ToString());
                }

                // log as WARN here and not ERROR - if method ends up returning false then it will bubble up and get logged as an ERROR
                LogHelper.Instance.Warning((int)ErrorCode.CertificateValidation, logEntry.ToString().Trim());
            }

            // determine env
            var isDev = EnvironmentHelper.IsDevelopment();
            var isTest = EnvironmentHelper.IsTest();

            // if env is dev or test then ignore cert errors and return true (reference any log entries created from logic above for troubleshooting)
            if (isDev || isTest)
                isValid = true;

            return isValid;
        }

注意:您需要禁用/更改部分自定义代码 - 指纹内容,日志记录等。

答案 1 :(得分:0)

将证书添加到CA受信任存储区只意味着您信任证书的颁发者,在这种情况下证书本身就是证书本身,因为它是自签名证书。缺少的是证书验证执行链检查和撤销检查,并且两个检查中的任何一个检查失败。请注意,即使您信任证书,它仍然可以在最近被撤销,因此不应该被信任。因此,始终需要进行撤销检查。对于测试,禁用吊销检查是一种方法。一个ADFS端,您可以禁用每个依赖方的撤销检查。如果检查发生在您自己的代码上,您可以完全禁用检查或使用Stinky Towel的代码来选择性地仅允许某些证书。

答案 2 :(得分:0)

似乎要解决错误,只需在我的网络服务器上添加ADFS令牌签名证书作为受信任的根证书颁发机构。

PS:我不确定为什么令牌签名证书链验证在加密被禁用时不会引发错误,以及它与加密有什么关系,但事实如此是因为它对我们用于测试的两种环境都有帮助。