【问题标题】:ADFS token encryption certificate chain validation failsADFS 令牌加密证书链验证失败
【发布时间】:2016-10-25 22:36:21
【问题描述】:

我有 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 服务器上的受信任根权限(以及一些其他“可疑”证书)。

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

【问题讨论】:

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


    【解决方案1】:

    看来要解决一个错误,在我的 Web 服务器上添加 ADFS 令牌签名证书作为受信任的根证书颁发机构就足够了。

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

    【讨论】:

      【解决方案2】:

      我使用 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;
              }
      

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

      【讨论】:

        【解决方案3】:

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

        【讨论】:

        • 如果我刚刚创建它,它如何被撤销?既然它是自签名的,你的意思是什么链验证?
        • 我没有说你的证书被吊销了。我说过,默认情况下,WIF/ADFS 会检查它是否已被吊销,如果他们无法执行检查,因为自签名证书既不提供 CRL 也不提供 OCSP,吊销检查被视为“失败”。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-06-25
        • 2012-03-15
        • 2016-01-19
        • 2017-01-12
        • 1970-01-01
        相关资源
        最近更新 更多