I've implemented SSO using Spring SAML and everything is working fine. It worked with the following IDP's till now: 1) idp.ssocircle.com 2) openidp.feide.no
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:
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"/>
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 Status 401 - This request requires HTTP authentication(Authentication Failed: Incoming SAML message is invalid).
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).
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.
Thanks,
Abhilash