I did everything as described in spring saml tutorial, except that I add
<dependency>
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
<version>1.4.01</version>
</dependency>
in pom.xml to overcome a w3.dom class not found problem. When I run the sample project, I got
HTTP Status 401 - Authentication Failed: Error decoding incoming SAML message
in browser, and at the same time (CertPathPKIXTrustEvaluator.java:81) ERROR org.springframework.security.saml.trust.MetadataCredentialResolver - PKIX path construction failed for untrusted credential: [subjectName='CN=idp.ssocircle.com' |credential entityID='https://idp.ssocircle.com']: unable to find valid certification path to requested target
in console.
DAY 2:
I ran keytool -importcert -alias identtrustca -file ca.cer -keystore samlKeystore.jks
and replace security/samlKeystore.jks
with the new generated one. The securityContext.xml
:
<bean id="keyManager" class="org.springframework.security.saml.key.JKSKeyManager">
<constructor-arg value="classpath:security/samlKeystore.jks"/>
<constructor-arg type="java.lang.String" value="nalle123"/>
<constructor-arg>
<map>
<entry key="apollo" value="nalle123"/>
</map>
</constructor-arg>
<constructor-arg type="java.lang.String" value="apollo"/>
</bean>
Then I have:
Caused by: java.io.IOException: Keystore was tampered with, or password was incorrect
at sun.security.provider.JavaKeyStore.engineLoad(Unknown Source)
at sun.security.provider.JavaKeyStore$JKS.engineLoad(Unknown Source)
at java.security.KeyStore.load(Unknown Source)
at org.springframework.security.saml.key.JKSKeyManager.initialize(JKSKeyManager.java:117)
... 57 more
Caused by: java.security.UnrecoverableKeyException: Password verification failed
... 61 more
Then I change the password with the one I entered when use keytool
:
<bean id="keyManager" class="org.springframework.security.saml.key.JKSKeyManager">
<constructor-arg value="classpath:security/samlKeystore.jks"/>
<constructor-arg type="java.lang.String" value="123456"/>
<constructor-arg>
<map>
<entry key="apollo" value="123456"/>
</map>
</constructor-arg>
<constructor-arg type="java.lang.String" value="apollo"/>
</bean>
Then console says:
Servlet.service() for servlet [jsp] in context with path [/spring-security-saml2-sample] threw exception
java.lang.RuntimeException: Key for alias apollo not found
at org.springframework.security.saml.metadata.MetadataGenerator.getServerKeyInfo(MetadataGenerator.java:201)
So I change apollo
to identtrustca
:
<bean id="keyManager" class="org.springframework.security.saml.key.JKSKeyManager">
<constructor-arg value="classpath:security/samlKeystore.jks"/>
<constructor-arg type="java.lang.String" value="123456"/>
<constructor-arg>
<map>
<entry key="identtrustca" value="123456"/>
</map>
</constructor-arg>
<constructor-arg type="java.lang.String" value="identtrustca"/>
</bean>
and console says:
Servlet.service() for servlet [jsp] in context with path [/spring-security-saml2-sample] threw exception
java.lang.UnsupportedOperationException: trusted certificate entries are not password-protected
Then I read this and this, so I delete the entry element (I believe it is the private key stuff), it becomes:
<bean id="keyManager" class="org.springframework.security.saml.key.JKSKeyManager">
<constructor-arg value="classpath:security/samlKeystore.jks"/>
<constructor-arg type="java.lang.String" value="123456"/>
<constructor-arg>
<map/>
</constructor-arg>
<constructor-arg type="java.lang.String" value="identtrustca"/>
</bean>
Now problem becomes:
Servlet.service() for servlet [jsp] in context with path [/spring-security-saml2-sample] threw exception
java.lang.RuntimeException: Key with alias identtrustca doesn't have a private key
DAY 2 2nd part:
Now I understand that instead of creating a new keystore I should just use the old samlKeystore.jks. And if using keytool -list -V -keystore d:\temp\samlKeystore.jks
one can see it contains 3 items (originally it has 2).
I don't understand why SP gets public key from IdP metadata, but still needs IdP's ca.cer? I believe the ca.cer from the auth website is IdP's certificate, although it is different from the one I get by openssl s_client -connect idp.ssocircle.com:443 -showcerts
Moreover, now instead of getting Error decoding incoming SAML message
, Now I am having HTTP Status 401 - Authentication Failed: Response issue time is either too old or with date in the future
DAY 3 When I start SP, visiting http://localhost:8080/spring-security-saml2-sample/ from both chrome and firefox, when I pressed global logout in one explorer, and refresh the other one, it does not show a log out page. I thought for SSO, global logout from the same SP should ignore multi-session, e.g., once I global logout in one "login", and I should automatically log out in the other one, I should see a log-out-page in the other explorer too (if I refresh). Actually, for multiple SPs, one I logout in one, I should be able to see logout in all SPs that I once logged in.
DAY n By changing the saml project url, one needs to modify metadata in idp.ssocircle.com (manage metadata). Otherwise, the idp website would show error. This is written in docs/reference/htmlsingle/index.html
Certificates in IDP metadata are used to digitally sign SAML XML documents. The certificate your failure comes from is from the HTTPS endpoint of www.ssocircle.com, which your Spring SAML calls during Artifact Resolution. Those two certificates are typically different.
SSOCircle recently changed the certification authority which issues their certificate for www.ssocircle.com, and the operation described in SAML ERROR: PKIX path construction failed for untrusted credential is to get that CA trusted.
Your latest error is likely caused by not having time on your Spring SAML machine correctly synchronized.