本文介绍了“HTTP 状态 401 - 身份验证失败:传入的 SAML 消息无效"使用 Salesforce 作为 IdP 来实施 SSO的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经使用 Spring SAML 实现了 SSO,并且一切正常.到目前为止,它与以下 IDP 一起工作:1) idp.ssocircle.com2) openidp.feide.no

I've implemented SSO using Spring SAML and everything is working fine. It worked with the following IDP's till now:1) idp.ssocircle.com2) openidp.feide.no

现在我正在使用 salesforce.com 作为我的身份提供者进行测试.由于没有上传服务提供商元数据的规定,我在其 IdP 中进行了以下配置设置:

Now I'm testing with salesforce.com as my Identity Provider. As there is no provision to upload Service Provider Metadata I've done the following configuration settings at its IdP:

提供我的 entityID 和断言消费者服务 URL.我还上传了我的 SP 证书.我已经下载了它的元数据(idp 元数据),如下(隐藏敏感信息):

Gave my entityID and Assertion Consumer Service URL. I also uploaded my SP certificate. I've downloaded its metadata (idp metadata) which is as follows (hiding the sensitive information):

<?xml version="1.0" encoding="UTF-8"?><md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" entityID="https://ABC-dev-ed.my.salesforce.com" validUntil="2024-04-11T13:55:57.307Z">
<md:IDPSSODescriptor WantAuthnRequestsSigned="true" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
  <md:KeyDescriptor use="signing">
     <ds:KeyInfo>
        <ds:X509Data>
           <ds:X509Certificate>XXXXXXXXX</ds:X509Certificate>
        </ds:X509Data>
     </ds:KeyInfo>
  </md:KeyDescriptor>
  <md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</md:NameIDFormat>
  <md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://ABC-dev-ed.my.salesforce.com/idp/endpoint/HttpPost"/>
  <md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://ABC-dev-ed.my.salesforce.com/idp/endpoint/HttpRedirect"/>

现在,当我尝试测试我的 SP 时,它首先将我重定向到 IDP(salesforce),要求我输入凭据,然后我被重定向回我的断言消费者服务 URL(这是我的 SP)但是这里产生了一个异常,说

Now when I tried to test my SP, first it redirected me to the IDP(salesforce) asking for credentials where I entered them but then after that I was redirected back to my Assertion consumer Service URL(which is my SP) but here an exception was generated saying that

HTTP 状态 401 - 此请求需要 HTTP 身份验证(身份验证失败:传入的 SAML 消息无效).

HTTP Status 401 - This request requires HTTP authentication(Authentication Failed: Incoming SAML message is invalid).

我尝试了以下但没有奏效:(-虽然不是必需的,但我已经从 salesforce 下载了证书文件并将其导入到我的 keystore.jks 中,以确保该密钥用于签名验证.(由于证书信息已存在于 IDP 元数据中,因此不需要).

I've tried the following but didn't work :( -Though not necessary, I've downloaded the certificate file from the salesforce and imported it to my keystore.jks so that to make sure that key is used for signature validation.(Not necessary due to the certificate info already present in IDP metadata).

这是我在日志文件中找到的内容(仅在成功 AuthnRequest 后添加必要信息):

Here is what I found in my log file(Adding necessary info only after successful AuthnRequest):

AuthNRequest;SUCCESS;127.0.0.1
.....STARTED_FAILING_HERE.....
Attempting to extract credential from an X509Data
Found 1 X509Certificates
Found 0 X509CRLs
Single certificate was present, treating as end-entity certificate
Credentials successfully extracted from child {http://www.w3.org/2000/09/xmldsig#}X509Data by provider org.opensaml.xml.security.keyinfo.provider.InlineX509DataProvider
A total of 1 credentials were resolved
Registry could not locate evaluable criteria for criteria class org.opensaml.xml.security.keyinfo.KeyInfoCriteria
Attempting to validate signature using key from supplied credential
Creating XMLSignature object
Validating signature with signature algorithm URI: http://www.w3.org/2000/09/xmldsig#rsa-sha1
Validation credential key algorithm 'RSA', key instance class 'sun.security.rsa.RSAPublicKeyImpl'
Signature validated with key from supplied credential
Signature validation using candidate credential was successful
Successfully verified signature using KeyInfo-derived credential
Attempting to establish trust of KeyInfo-derived credential
Failed to validate untrusted credential against trusted key
Failed to establish trust of KeyInfo-derived credential
Failed to verify signature and/or establish trust using any KeyInfo-derived credentials
Attempting to verify signature using trusted credentials
Attempting to validate signature using key from supplied credential
Creating XMLSignature object
Validating signature with signature algorithm URI: http://www.w3.org/2000/09/xmldsig#rsa-sha1
Validation credential key algorithm 'RSA', key instance class 'sun.security.rsa.RSAPublicKeyImpl'
Signature did not validate against the credential's key
Signature validation using candidate validation credential failed
org.opensaml.xml.validation.ValidationException: Signature did not validate against the credential's key
at org.opensaml.xml.signature.SignatureValidator.validate(SignatureValidator.java:79)
at org.opensaml.xml.signature.impl.BaseSignatureTrustEngine.verifySignature(BaseSignatureTrustEngine.java:142)
at org.opensaml.xml.signature.impl.ExplicitKeySignatureTrustEngine.validate(ExplicitKeySignatureTrustEngine.java:110)
at org.opensaml.xml.signature.impl.ExplicitKeySignatureTrustEngine.validate(ExplicitKeySignatureTrustEngine.java:49)
at org.opensaml.ws.security.provider.BaseTrustEngineRule.evaluate(BaseTrustEngineRule.java:104)
at org.opensaml.ws.security.provider.BaseTrustEngineRule.evaluate(BaseTrustEngineRule.java:91)
at org.opensaml.common.binding.security.SAMLProtocolMessageXMLSignatureSecurityPolicyRule.doEvaluate(SAMLProtocolMessageXMLSignatureSecurityPolicyRule.java:128)
at org.opensaml.common.binding.security.SAMLProtocolMessageXMLSignatureSecurityPolicyRule.evaluate(SAMLProtocolMessageXMLSignatureSecurityPolicyRule.java:107)
at org.opensaml.ws.security.provider.BasicSecurityPolicy.evaluate(BasicSecurityPolicy.java:51)
at org.opensaml.ws.message.decoder.BaseMessageDecoder.processSecurityPolicy(BaseMessageDecoder.java:132)
at org.opensaml.ws.message.decoder.BaseMessageDecoder.decode(BaseMessageDecoder.java:83)
at org.opensaml.saml2.binding.decoding.BaseSAML2MessageDecoder.decode(BaseSAML2MessageDecoder.java:70)
at org.springframework.security.saml.processor.SAMLProcessorImpl.retrieveMessage(SAMLProcessorImpl.java:105)
at org.springframework.security.saml.processor.SAMLProcessorImpl.retrieveMessage(SAMLProcessorImpl.java:172)
at org.springframework.security.saml.SAMLProcessingFilter.attemptAuthentication(SAMLProcessingFilter.java:77)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:195)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:166)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:164)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:462)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:403)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:301)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:162)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:140)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:309)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
Failed to verify signature using either KeyInfo-derived or directly trusted credentials
Validation of protocol message signature failed for context issuer 'https://ABC-dev-ed.my.salesforce.com', message type: {urn:oasis:names:tc:SAML:2.0:protocol}Response
Authentication request failed: org.springframework.security.authentication.AuthenticationServiceException: Incoming SAML message is invalid
Updated SecurityContextHolder to contain null Authentication
Delegating to authentication failure handler org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler@153a591

有人可以通过查看上面的日志告诉我出了什么问题.任何帮助将不胜感激.

Can someone please tell me what is going wrong by looking at the above log. Any help would be highly appreciated.

谢谢,

阿比拉什

推荐答案

您的 IDP 使用的数字签名密钥与其在元数据中定义的密钥不同.

Your IDP is using a different key for digital signatures than it defines in metadata.

您应该检查收到的 SAML 消息,并在元素签名中查找元素 X509Certificate.将证书的内容提取到一个单独的文件中,例如sales-force-sign.cer

You should inspect the SAML message you received and look for element X509Certificate inside element Signature. Extract the content of the certificate into a separate file, e.g. sales-force-sign.cer

然后您需要将证书导入您的 samlKeystore.jks,您可以在 Spring SAML 手册的第 4.5 章(密钥管理).请务必记下您导入密钥时使用的别名.

You then need to import the certificate into your samlKeystore.jks, you can find details on how to do it in chapter 4.5 (Key management) of the Spring SAML manual. Make sure to note the alias you import the key with.

作为最后一步,您需要告诉 Spring SAML 使用新导入的密钥对您的 IDP 进行签名验证,为此您应该更新您的 securityContext.xml 并使用属性 signatureKey 和您的别名的值更新您的 IDP 的 ExtendedMetadta之前用于导入密钥.它看起来类似于:

As last step you need to tell Spring SAML to use the newly imported key for signature verifications for your IDP, for that you should update your securityContext.xml and update your ExtendedMetadta for your IDP with property signingKey and value of the alias you used earlier to import the key. It will look similar to:

  <bean class="org.springframework.security.saml.metadata.ExtendedMetadataDelegate">
      <constructor-arg>
          <bean class="org.opensaml.saml2.metadata.provider.FilesystemMetadataProvider">
              <constructor-arg>
                  <value type="java.io.File">classpath:salesforce_metadata.xml</value>
              </constructor-arg>
              <property name="parserPool" ref="parserPool"/>
          </bean>
      </constructor-arg>
      <constructor-arg>
          <bean class="org.springframework.security.saml.metadata.ExtendedMetadata">
              <property name="signingKey" value="sf-proxy"/>
          </bean>
      </constructor-arg>
  </bean>

同样,您可以在手册中找到所有这些的详细信息.

Again you can find details on all of this in the manual.

或者,您可以简单地将您从消息中提取的密钥添加到您的 IDP 元数据中.只需手动更新 XML 文件并添加另一个带有 use="signing" 的 KeyDescriptor.这样做可能会更快.

Alternatively you can simply add the key you extracted from the message into your IDP metadata. Just manualy update the XML file and add another KeyDescriptor with use="signing". It might be faster to do.

这篇关于“HTTP 状态 401 - 身份验证失败:传入的 SAML 消息无效"使用 Salesforce 作为 IdP 来实施 SSO的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-16 21:48