title: Integrating Spring SAML as SP and SimpleSAMLphp as IdP (HoK profile)
body: <p>I am trying to get HoK profile work with Spring SAML as the SP and SimpleSAMLphp as the IdP.</p>
  
  <p>The SP gets the client certificate and then sends the following authentication request to the IdP without problem:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;saml2p:AuthnRequest
      AssertionConsumerServiceURL="https://sp.com/saml/HoKSSO"
      Destination="https://localhost:8443/simplesaml/saml2   /idp/SSOService.php"
      ForceAuthn="false" ID="a5ba2704fgc63887442i9i1298904fh"
      IsPassive="false" IssueInstant="2015-10-04T11:26:47.393Z"
      ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
      Version="2.0" xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol"&gt;
      &lt;saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion"&gt;https://sp.com/saml/metadata&lt;/saml2:Issuer&gt;
  &lt;/saml2p:AuthnRequest&gt;
  </code></pre>
  
  <p>In response, the IdP requests for the client certificate during TLS handshake and then gets his username/password and authenticates him successfully. It sends the following response:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;samlp:Response Destination="https://sp.com/saml/HoKSSO"
      ID="_94c3201b7ae79d95f8ef289705c406bd61b8ed81f1"
      InResponseTo="a5ba2704fgc63887442i9i1298904fh"
      IssueInstant="2015-10-04T11:26:47Z" Version="2.0"
      xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"&gt;
      &lt;saml:Issuer&gt;https://localhost:8443/simplesaml/saml2/idp/metadata.php&lt;/saml:Issuer&gt;
      &lt;samlp:Status&gt;
          &lt;samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/&gt;
      &lt;/samlp:Status&gt;
      &lt;saml:Assertion ID="_b703fd12c6692e7a5d431d539888fcb01171a41f92"
          IssueInstant="2015-10-04T11:26:47Z" Version="2.0"
          xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&gt;
          &lt;saml:Issuer&gt;https://localhost:8443/simplesaml/saml2/idp/metadata.php&lt;/saml:Issuer&gt;
          &lt;saml:Subject&gt;
              &lt;saml:NameID
                  Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress" SPNameQualifier="https://sp.com/saml/metadata"&gt;b9bdc06e4c25f5a464c6d5586394d6922031bd1d&lt;/saml:NameID&gt;
              &lt;saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:holder-of-key"&gt;
                  &lt;saml:SubjectConfirmationData
                      InResponseTo="a5ba2704fgc63887442i9i1298904fh"
                      NotOnOrAfter="2015-10-04T11:31:47Z" Recipient="https://sp.com/saml/HoKSSO"&gt;
                      &lt;ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"&gt;
                          &lt;ds:X509Data&gt;
                              &lt;ds:X509Certificate&gt;MIIFiDCCA3CgAwIBAgIQbAEaDQN5v8UJ7CM03ArefzANBgkqhkiG9w0BAQsFADBJMQswCQYDVQQGEwJJUjEYMBYGA1UECgwPSXJhbiBHb3Zlcm5tZW50MSAwHgYDVQQDDBdUZXN0QmVkMiBJUkFOIEFkbWluIENBMTAeFw0xMzExMTExMjQyNTdaFw0xNTExMTExMjQyNTdaMEsxCzAJBgNVBAYTAklSMQ0wCwYDVQQKDAROT0NSMRYwFAYDVQQDDA1oIGFtaXJpIC0gU0NMMRUwEwYDVQQFEwxpcjA1Njk5NTk1OTQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDSTKy+pttM92iH9EIo5eBiI8aJRTfLAUrjY7Wsts4qJjj08CCrYsFdw6PLVFRhOCG8xK1YXQ+vgl3FBFDrJVj3Gg43izirUoDANCGIvABMrOekRfR62YRDpah7A8e4tA27Uo7WBPqhISClyUvRifDZSYVsf08vQZCE48jEUpaxDhhLW1gED82a5dGDbR9S6PauVLsSR4z4mkPGMxLiERIgTimcpUyt1bMRcFGAQIQs0NGNssH6CHOWWBfPICFwixvoejWjMjgwWCNGBuQduuIu2nqYIJ5eoNh+8kUIcS77RTcNZnUki8fkbIvZpl9yuS85L8OADfThf+AZpPCXar0RAgMBAAGjggFoMIIBZDAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBQogn5DJWYIWEPWrkh1e7hZWqBApDAfBgNVHSMEGDAWgBQgILBuWsWyApOxBN+fWtk5GuDPjjAOBgNVHQ8BAf8EBAMCBaAwCQYDVR0gBAIwADAfBgNVHSUEGDAWBggrBgEFBQcDAgYKKwYBBAGCNxQCAjA9BgNVHREENjA0gRRpcjA1Njk5NTk1OTRAaXJhbi5pcqAcBgorBgEEAYI3FAIDoA4MDGlyMDU2OTk1OTU5NDBFBgNVHR8EPjA8MDqgOKA2hjRodHRwOi8vQ1JMRFBUb0JlRGVmaW5lZC9BUkwvVGVzdEJlZDJJUkFOQWRtaW5DQTEuY3JsMFIGCCsGAQUFBwEBBEYwRDBCBggrBgEFBQcwAoY2aHR0cDovL3BrZC5pcmFuaWQuaXIvL0NBQ2VydHMvVGVzdEJlZDJJUkFOQWRtaW5DQTEuY3J0MA0GCSqGSIb3DQEBCwUAA4ICAQBoxP6xmLLdNCsdQ1S6cP/ZhadtCXiVdnvjnQOr43iTHRwdHIcGuQyMpmOQFAi/IhvPMWXK2DAnCW3UQi4csZpAl0MtRQU+BpCOzb47sihqxJX69hKXQQUHRYpyzAXBoA0yFfqKM/Q1MoqqZD/z4y3Anma7vF1vlGqWYRqHSY/jSa+10IlEw4WHC24FCw06Tz8w2h3MFfrzB+vDBZ6jndy5c2+XEFdIGdk/8QFYndkC9lfrpfVDEl8Qq6P+dyZPIA8fFCfE/4qadhMsytU9bmwq92K3/wXKjg0dnJJte+zC9O8qqCU5aBmIIGiaB5NIQaSmZXMFeFcgwKzPtyUZVOosTyeDwrhDiSaup2EU2UapGlPyl6FM6BrGu1gdSRSjOJd2YOM0y7GFP/2TqImLC7wREI5eK/zjDZyNjE5XOA7eZkODgZy+sD5Zj9pKsZYCQxRSZe16awnIZ5QWERVUNKjQgm9BPx1evLE4rCxj6e1aorecR/uJjKtUjuJNxF+DI83Rnj3TBIzyxPM0YEB8iro0qBzEO6MVnVR251qYpN0Mu3qHJk9kHa+RwK7gpIiC/gqN/u/O+D4h0tFJ/dfE6UP3SR0et/Hs3Yby0hhyt3C7UgXHEyVGSkyr1yYUrdQK2Qyoktv9xCqUwZ+OFiHECBC9ZaF8kqPi9VsVqf5OjX9TQg==&lt;/ds:X509Certificate&gt;
                          &lt;/ds:X509Data&gt;
                      &lt;/ds:KeyInfo&gt;
                  &lt;/saml:SubjectConfirmationData&gt;
              &lt;/saml:SubjectConfirmation&gt;
          &lt;/saml:Subject&gt;
          &lt;saml:Conditions NotBefore="2015-10-04T11:26:17Z" NotOnOrAfter="2015-10-04T11:31:47Z"&gt;
              &lt;saml:AudienceRestriction&gt;
                  &lt;saml:Audience&gt;https://sp.com/saml/metadata&lt;/saml:Audience&gt;
              &lt;/saml:AudienceRestriction&gt;
          &lt;/saml:Conditions&gt;
          &lt;saml:AuthnStatement AuthnInstant="2015-10-04T11:08:06Z"
              SessionIndex="_2e1ddd44e4b2215a074312dc7a1e31865dd940f49f" SessionNotOnOrAfter="2015-10-04T19:26:47Z"&gt;
              &lt;saml:AuthnContext&gt;
                  &lt;saml:AuthnContextClassRef&gt;urn:oasis:names:tc:SAML:2.0:ac:classes:Password&lt;/saml:AuthnContextClassRef&gt;
              &lt;/saml:AuthnContext&gt;
          &lt;/saml:AuthnStatement&gt;
          &lt;saml:AttributeStatement&gt;
              &lt;saml:Attribute Name="urn:oid:0.9.2342.19200300.100.1.1" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"&gt;
                  &lt;saml:AttributeValue xsi:type="xs:string"&gt;student&lt;/saml:AttributeValue&gt;
              &lt;/saml:Attribute&gt;
              &lt;saml:Attribute Name="urn:oid:1.3.6.1.4.1.5923.1.1.1.1" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"&gt;
                  &lt;saml:AttributeValue xsi:type="xs:string"&gt;member&lt;/saml:AttributeValue&gt;
                  &lt;saml:AttributeValue xsi:type="xs:string"&gt;student&lt;/saml:AttributeValue&gt;
              &lt;/saml:Attribute&gt;
          &lt;/saml:AttributeStatement&gt;
      &lt;/saml:Assertion&gt;
  &lt;/samlp:Response&gt;
  </code></pre>
  
  <p>Everything seems OK but Spring SAML throws the following exception:</p>
  
  <pre><code>org.springframework.security.authentication.AuthenticationServiceException: Error validating SAML message
  at org.springframework.security.saml.SAMLAuthenticationProvider.authenticate(SAMLAuthenticationProvider.java:95)
  at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:167)
  at org.springframework.security.saml.SAMLProcessingFilter.attemptAuthentication(SAMLProcessingFilter.java:87)
  at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:217)
  at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
  at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213)
  at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:184)
  at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
  at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64)
  at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
  at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
  at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:53)
  at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
  at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
  at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:91)
  at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
  at org.springframework.security.web.access.channel.ChannelProcessingFilter.doFilter(ChannelProcessingFilter.java:152)
  at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
  at org.springframework.security.saml.metadata.MetadataGeneratorFilter.doFilter(MetadataGeneratorFilter.java:87)
  at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
  at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213)
  at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:176)
  at org.springframework.security.web.debug.DebugFilter.invokeWithWrappedRequest(DebugFilter.java:75)
  at org.springframework.security.web.debug.DebugFilter.doFilter(DebugFilter.java:62)
  at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
  at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
  at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:221)
  at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:107)
  at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:504)
  at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:155)
  at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:76)
  at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:934)
  at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:90)
  at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:515)
  at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1012)
  at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:642)
  at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:223)
  at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1597)
  at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1555)
  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
  at java.lang.Thread.run(Thread.java:744)
  Caused by: org.opensaml.common.SAMLException: Response doesn't have any valid assertion which would pass subject validation
  at org.springframework.security.saml.websso.WebSSOProfileConsumerImpl.processAuthenticationResponse(WebSSOProfileConsumerImpl.java:229)
  at org.springframework.security.saml.SAMLAuthenticationProvider.authenticate(SAMLAuthenticationProvider.java:84)
  ... 43 more
  Caused by: org.opensaml.common.SAMLException: Assertion invalidated by subject confirmation - can't be confirmed by holder-of-key method
  at org.springframework.security.saml.websso.WebSSOProfileConsumerHoKImpl.verifySubject(WebSSOProfileConsumerHoKImpl.java:150)
  at org.springframework.security.saml.websso.WebSSOProfileConsumerImpl.verifyAssertion(WebSSOProfileConsumerImpl.java:296)
  at org.springframework.security.saml.websso.WebSSOProfileConsumerImpl.processAuthenticationResponse(WebSSOProfileConsumerImpl.java:214)
  ... 44 more
  </code></pre>
  
  <p>Spring SAML debugging logs here:</p>
  
  <pre><code>8532 [http-nio-443-exec-9] DEBUG   - Evaluating security policy of type 'org.opensaml.ws.security.provider.BasicSecurityPolicy' for decoded message
  8532 [http-nio-443-exec-9] DEBUG   - Evaluating simple signature rule of type: org.opensaml.saml2.binding.security.SAML2HTTPPostSimpleSignRule
  8532 [http-nio-443-exec-9] DEBUG   - HTTP request was not signed via simple signature mechanism, skipping
  8532 [http-nio-443-exec-9] INFO    - SAML protocol message was not signed, skipping XML signature processing
  8532 [http-nio-443-exec-9] DEBUG   - Successfully decoded message.
  8532 [http-nio-443-exec-9] DEBUG   - Checking SAML message intended destination endpoint against receiver endpoint
  8533 [http-nio-443-exec-9] DEBUG   - Intended message destination endpoint: https://cmks.irannid.ir/saml/HoKSSO
  8533 [http-nio-443-exec-9] DEBUG   - Actual message receiver endpoint: https://cmks.irannid.ir/saml/HoKSSO
  8533 [http-nio-443-exec-9] DEBUG   - SAML message intended destination endpoint matched recipient endpoint
  8533 [http-nio-443-exec-9] DEBUG   - Found endpoint org.opensaml.saml2.metadata.impl.AssertionConsumerServiceImpl@38620660 for request URL https://cmks.irannid.ir/saml/HoKSSO based on location attribute in metadata
  8534 [http-nio-443-exec-9] DEBUG   - Authentication attempt using org.springframework.security.saml.SAMLAuthenticationProvider
  8534 [http-nio-443-exec-9] DEBUG   - Verifying issuer of the Response
  8535 [http-nio-443-exec-9] DEBUG   - Processing Holder-of-Key subject confirmation
  8535 [http-nio-443-exec-9] DEBUG   - HoK SubjectConfirmation invalidated by confirmation data not being of KeyInformationDataType type
  8535 [http-nio-443-exec-9] DEBUG   - Validation of authentication statement in assertion failed, skipping
  </code></pre>
  
  <p>The error is: <strong>HoK SubjectConfirmation invalidated by confirmation data not being of KeyInformationDataType type</strong>. It seems that Spring SAML could not find KeyInfo in the response!!</p>
  
  <p>Can anybody help me resolve this problem?</p>
  
  <p>Thank you</p>
  
  <p><strong>Edit:</strong></p>
  
  <p>By comparing with sample HoK SSO responses, it sees that SimpleSAMLphp has not added <strong>xsi:type="saml:KeyInfoConfirmationDataType"</strong> to the SubjectConfirmationData tag. Can it be the reason of the above exception?</p>
  
  <p>Is it a mandatory attribute for the SubjectConfirmationData tag in SAML2.0 HoK profile?</p>