spring-securitydigital-signaturex509saml-2.0spring-saml

Spring Security SAML - Failed to verify signature


I'm using the Spring Security SAML 2.0 sample webapp on Tomcat 7 and have modified it to try to get it to authenticate against a Ping Identity service. The webapp is talking to the service and it's sending back an assertion, but it's failing when trying to verify the signature, as shown by the debug output below:

- Attempting to verify signature and establish trust using KeyInfo-derived credentials
- Signature contained no KeyInfo element, could not resolve verification credentials
- Failed to verify signature and/or establish trust using any KeyInfo-derived credentials
- Attempting to verify signature using trusted credentials
- Failed to verify signature using either KeyInfo-derived or directly trusted credentials
- Validation of received assertion failed, assertion will be skipped
org.opensaml.xml.validation.ValidationException: Signature is not trusted or invalid

I understand that it's not able to verify the signature, and I have been given a certificate by the Ping Identity admins to use, but I'm unsure of how to include it in the application. I've tried adding it to the JKS (keystore) that comes with the sample application using the JDK's keytool program, but it can't seem to find it in there. I've also tried adding it to the service provider's metadata xml file like this:

<md:KeyDescriptor use="signing">
    <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
        <ds:X509Data>
            <ds:X509Certificate>
                [Certificate is here...]
            </ds:X509Certificate>
        </ds:X509Data>
    </ds:KeyInfo>
</md:KeyDescriptor>

However it still returns the same error.

Is there a specific place I should put the certificate in order to validate the signature? I'm relatively new to SAML and application security in general, so I apologise if I'm using the wrong terminology.


Solution

  • Finally got this to work. Turns out I'd missed out a line of configuration in the security context file, and that (it appears as though) no X509 certificate definition was needed in the service provider's metadata XML file.

    Basically I'd already imported the public key I'd been provided with into the existing JKS (using keytool), but I hadn't told the application to specifically use this. In order to do this, I had to go into the security context file (in my case "securityContext.xml") and add the following line to the ExtendedMetadata bean definition for the SP's metadata xml file:

    <property name="signingKey" value="[alias of the provided key in the JKS goes here]"/>
    

    Hence after this modification, the ExtendedMetadataDelegate bean definition looked like this:

    <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:security/[Path to SP metadata xml file].xml</value>
          </constructor-arg>
          <property name="parserPool" ref="parserPool" />
        </bean>
      </constructor-arg>
      <constructor-arg>
        <bean class="org.springframework.security.saml.metadata.ExtendedMetadata">
          <property name="alias" value="[SP alias goes here]" />
          <property name="signingKey" value="[alias of the provided key in the JKS goes here]"/>
        </bean>
      </constructor-arg>
    </bean>
    

    Hope this helps anyone who might be in a similar situation.