Spring SAML application for security security does not work for me when I integrate it with PingIdentity. After receiving the redirect to idp, loggin to Ping ok, having received a good saml statement, redirect back to the SAML security application in Spring, I get an infinite loop with an access denied error in the spring-security stack. And the org.sourceid error in Ping. Error in the Ping log (right before making a good SAML statement):
org.sourceid.saml20.profiles.StatusResponseException: Unknown AssertionConsumerServiceURL https://xxxwm07.integration.company.at:9031/sp/ACS.saml2
Access Denial Error in Spring:
2017-09-18 09:48:00 INFO stdout:71 – 2017-09-18 09:48:00 DEBUG HttpSessionStorage:93 – Storing message a2iiedhi69h081391e3biag591i7a2f to session FVAX79n-fxixNnIApUrrLe2V
2017-09-18 09:48:00 DEBUG HttpSessionStorage:93 – Storing message a2iiedhi69h081391e3biag591i7a2f to session FVAX79n-fxixNnIApUrrLe2V
2017-09-18 09:48:00 INFO stdout:71 – 2017-09-18 09:48:00 INFO SAMLDefaultLogger:127 – AuthNRequest;SUCCESS;10.69.208.181;app1;pingidentity;;;
2017-09-18 09:48:00 INFO SAMLDefaultLogger:127 – AuthNRequest;SUCCESS;10.69.208.18;app1;pingidentity;;;
2017-09-18 09:48:00 INFO stdout:71 – 2017-09-18 09:48:00 DEBUG SecurityContextPersistenceFilter:97 – SecurityContextHolder now cleared, as request processing completed
2017-09-18 09:48:01 INFO stdout:71 – 2017-09-18 09:48:01 DEBUG AntPathRequestMatcher:103 – Checking match of request : ‘/index.jsp’; against ‘/favicon.ico’
2017-09-18 09:48:01 INFO stdout:71 – 2017-09-18 09:48:01 DEBUG AntPathRequestMatcher:103 – Checking match of request : ‘/index.jsp’; against ‘/images/**’
2017-09-18 09:48:01 INFO stdout:71 – 2017-09-18 09:48:01 DEBUG AntPathRequestMatcher:103 – Checking match of request : ‘/index.jsp’; against ‘/css/**’
2017-09-18 09:48:01 INFO stdout:71 – 2017-09-18 09:48:01 DEBUG AntPathRequestMatcher:103 – Checking match of request : ‘/index.jsp’; against ‘/logout.jsp’
2017-09-18 09:48:01 INFO stdout:71 – 2017-09-18 09:48:01 DEBUG AntPathRequestMatcher:103 – Checking match of request : ‘/index.jsp’; against ‘/saml/web/**’
2017-09-18 09:48:01 INFO stdout:71 – 2017-09-18 09:48:01 DEBUG FilterChainProxy:337 – /index.jsp at position 1 of 8 in additional filter chain; firing Filter: ‘SecurityContextPersistenceFilter’
2017-09-18 09:48:01 INFO stdout:71 – 2017-09-18 09:48:01 DEBUG HttpSessionSecurityContextRepository:139 – HttpSession returned null object for SPRING_SECURITY_CONTEXT
2017-09-18 09:48:01 INFO stdout:71 – 2017-09-18 09:48:01 DEBUG HttpSessionSecurityContextRepository:85 – No SecurityContext was available from the HttpSession: org.apache.catalina.session.StandardSessionFacade@2f3ea906. A new one will be created.
2017-09-18 09:48:01 INFO stdout:71 – 2017-09-18 09:48:01 DEBUG FilterChainProxy:337 – /index.jsp at position 2 of 8 in additional filter chain; firing Filter: ‘FilterChainProxy’
2017-09-18 09:48:01 INFO stdout:71 – 2017-09-18 09:48:01 DEBUG AntPathRequestMatcher:103 – Checking match of request : ‘/index.jsp’; against ‘/saml/login/**’
2017-09-18 09:48:01 INFO stdout:71 – 2017-09-18 09:48:01 DEBUG AntPathRequestMatcher:103 – Checking match of request : ‘/index.jsp’; against ‘/saml/logout/**’
2017-09-18 09:48:01 INFO stdout:71 – 2017-09-18 09:48:01 DEBUG AntPathRequestMatcher:103 – Checking match of request : ‘/index.jsp’; against ‘/saml/metadata/**’
2017-09-18 09:48:01 INFO stdout:71 – 2017-09-18 09:48:01 DEBUG AntPathRequestMatcher:103 – Checking match of request : ‘/index.jsp’; against ‘/saml/sso/**’
2017-09-18 09:48:01 INFO stdout:71 – 2017-09-18 09:48:01 DEBUG AntPathRequestMatcher:103 – Checking match of request : ‘/index.jsp’; against ‘/saml/ssohok/**’
2017-09-18 09:48:01 INFO stdout:71 – 2017-09-18 09:48:01 DEBUG AntPathRequestMatcher:103 – Checking match of request : ‘/index.jsp’; against ‘/saml/singlelogout/**’
2017-09-18 09:48:01 INFO stdout:71 – 2017-09-18 09:48:01 DEBUG AntPathRequestMatcher:103 – Checking match of request : ‘/index.jsp’; against ‘/saml/discovery/**’
2017-09-18 09:48:01 INFO stdout:71 – 2017-09-18 09:48:01 DEBUG FilterChainProxy:180 – /index.jsp has no matching filters
2017-09-18 09:48:01 INFO stdout:71 – 2017-09-18 09:48:01 DEBUG FilterChainProxy:337 – /index.jsp at position 3 of 8 in additional filter chain; firing Filter: ‘RequestCacheAwareFilter’
2017-09-18 09:48:01 INFO stdout:71 – 2017-09-18 09:48:01 DEBUG DefaultSavedRequest:309 – pathInfo: both null (property equals)
2017-09-18 09:48:01 INFO stdout:71 – 2017-09-18 09:48:01 DEBUG DefaultSavedRequest:309 – queryString: both null (property equals)
2017-09-18 09:48:01 INFO stdout:71 – 2017-09-18 09:48:01 DEBUG DefaultSavedRequest:325 – requestURI: arg1=/app1/; arg2=/app1/ (property equals)
2017-09-18 09:48:01 INFO stdout:71 – 2017-09-18 09:48:01 DEBUG DefaultSavedRequest:325 – serverPort: arg1=8443; arg2=8443 (property equals)
2017-09-18 09:48:01 INFO stdout:71 – 2017-09-18 09:48:01 DEBUG DefaultSavedRequest:325 – requestURL: arg1=https://xxxwm07.integration.company.at:8443/app1/; arg2=https://xxxwm07.integration.company.at:8443/app1/ (property equals)
2017-09-18 09:48:01 INFO stdout:71 – 2017-09-18 09:48:01 DEBUG DefaultSavedRequest:325 – scheme: arg1=https; arg2=https (property equals)
2017-09-18 09:48:01 INFO stdout:71 – 2017-09-18 09:48:01 DEBUG DefaultSavedRequest:325 – serverName: arg1=xxxwm07.integration.company.at; arg2=xxxwm07.integration.company.at (property equals)
2017-09-18 09:48:01 INFO stdout:71 – 2017-09-18 09:48:01 DEBUG DefaultSavedRequest:325 – contextPath: arg1=/app1; arg2=/app1 (property equals)
2017-09-18 09:48:01 INFO stdout:71 – 2017-09-18 09:48:01 DEBUG DefaultSavedRequest:325 – servletPath: arg1=/index.jsp; arg2=/index.jsp (property equals)
2017-09-18 09:48:01 INFO stdout:71 – 2017-09-18 09:48:01 DEBUG HttpSessionRequestCache:62 – Removing DefaultSavedRequest from session if present
2017-09-18 09:48:01 INFO stdout:71 – 2017-09-18 09:48:01 DEBUG FilterChainProxy:337 – /index.jsp at position 4 of 8 in additional filter chain; firing Filter: ‘SecurityContextHolderAwareRequestFilter’
2017-09-18 09:48:01 INFO stdout:71 – 2017-09-18 09:48:01 DEBUG FilterChainProxy:337 – /index.jsp at position 5 of 8 in additional filter chain; firing Filter: ‘AnonymousAuthenticationFilter’
2017-09-18 09:48:01 INFO stdout:71 – 2017-09-18 09:48:01 DEBUG AnonymousAuthenticationFilter:102 – Populated SecurityContextHolder with anonymous token: ‘org.springframework.security.authentication.AnonymousAuthenticationToken@905571d8: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@0: RemoteIpAddress: 10.69.208.181; SessionId: FVAX79n-fxixNnIApUrrLe2V; Granted Authorities: ROLE_ANONYMOUS’
2017-09-18 09:48:01 INFO stdout:71 – 2017-09-18 09:48:01 DEBUG FilterChainProxy:337 – /index.jsp at position 6 of 8 in additional filter chain; firing Filter: ‘SessionManagementFilter’
2017-09-18 09:48:01 INFO stdout:71 – 2017-09-18 09:48:01 DEBUG FilterChainProxy:337 – /index.jsp at position 7 of 8 in additional filter chain; firing Filter: ‘ExceptionTranslationFilter’
2017-09-18 09:48:01 INFO stdout:71 – 2017-09-18 09:48:01 DEBUG FilterChainProxy:337 – /index.jsp at position 8 of 8 in additional filter chain; firing Filter: ‘FilterSecurityInterceptor’
2017-09-18 09:48:01 INFO stdout:71 – 2017-09-18 09:48:01 DEBUG FilterSecurityInterceptor:194 – Secure object: FilterInvocation: URL: /index.jsp; Attributes: [IS_AUTHENTICATED_FULLY]
2017-09-18 09:48:01 INFO stdout:71 – 2017-09-18 09:48:01 DEBUG FilterSecurityInterceptor:310 – Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@905571d8: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@0: RemoteIpAddress: 10.69.208.18; SessionId: FVAX79n-fxixNnIApUrrLe2V; Granted Authorities: ROLE_ANONYMOUS
2017-09-18 09:48:01 INFO stdout:71 – 2017-09-18 09:48:01 DEBUG AffirmativeBased:65 – Voter: org.springframework.security.access.vote.RoleVoter@18d957ee, returned: 0
2017-09-18 09:48:01 INFO stdout:71 – 2017-09-18 09:48:01 DEBUG AffirmativeBased:65 – Voter: org.springframework.security.access.vote.AuthenticatedVoter@651bd700, returned: -1
2017-09-18 09:48:01 INFO stdout:71 – 2017-09-18 09:48:01 DEBUG ExceptionTranslationFilter:165 – Access is denied (user is anonymous); redirecting to authentication entry point
2017-09-18 09:48:01 INFO stdout:71 – org.springframework.security.access.AccessDeniedException: Access is denied
2017-09-18 09:48:01 INFO stdout:71 – at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:83)
I'm going to get back to debugging Spring Security, but if you have any tips, this will be awesome. as you can see in this Spring sec log, everything looks fine with ping, the role selector is fine, then the authenticated user selector fails. and why do I end up as an anonymous user after a good ping authentication? It seems some kind of user principle should be matched with ping on spring, yes?
If only a hint on where to start in my Spring Security debugging would be very helpful ...
Thanks in advance
Both versions of IdP and SP in the Spring SAML Sample application are file based. Here are the details:
******* securityConext.xml
<bean id="metadata"
class="org.springframework.security.saml.metadata.CachingMetadataManager">
<constructor-arg>
<list>
<bean
class="org.springframework.security.saml.metadata.ExtendedMetadataDelegate">
<constructor-arg>
<bean
class="org.opensaml.saml2.metadata.provider.ResourceBackedMetadataProvider">
<constructor-arg>
<bean class="java.util.Timer" />
</constructor-arg>
<constructor-arg>
<bean class="org.opensaml.util.resource.ClasspathResource">
<constructor-arg value="/metadata/idp.xml" />
</bean>
</constructor-arg>
<property name="parserPool" ref="parserPool" />
</bean>
</constructor-arg>
<constructor-arg>
<bean
class="org.springframework.security.saml.metadata.ExtendedMetadata" />
</constructor-arg>
<property name="metadataTrustCheck" value="false" />
</bean>
<bean
class="org.springframework.security.saml.metadata.ExtendedMetadataDelegate">
<constructor-arg>
<bean
class="org.opensaml.saml2.metadata.provider.ResourceBackedMetadataProvider">
<constructor-arg>
<bean class="java.util.Timer" />
</constructor-arg>
<constructor-arg>
<bean class="org.opensaml.util.resource.ClasspathResource">
<constructor-arg value="/metadata/sp.xml" />
</bean>
</constructor-arg>
<property name="parserPool" ref="parserPool" />
</bean>
</constructor-arg>
<constructor-arg>
<bean
class="org.springframework.security.saml.metadata.ExtendedMetadata">
<property name="local" value="true" />
<property name="securityProfile" value="pkix" />
<property name="sslSecurityProfile" value="pkix" />
<property name="sslHostnameVerification" value="default" />
<property name="signMetadata" value="false" />
<property name="signingKey" value="ping" />
<property name="encryptionKey" value="mykey" />
<property name="tlsKey" value="ping" />
<property name="requireArtifactResolveSigned" value="false" />
<property name="requireLogoutRequestSigned" value="false" />
<property name="requireLogoutResponseSigned" value="false" />
<property name="idpDiscoveryEnabled" value="false" />
<property name="idpDiscoveryURL" value="http://www.google.com" />
<property name="idpDiscoveryResponseURL" value="http://www.google.com" />
</bean>
</constructor-arg>
</bean>
</list>
</constructor-arg>
</bean>
***** idp.xml
<md:EntityDescriptor ID="jWQF6vBDwO-0.YYnI3YL91qXp-O"
cacheDuration="PT1440M" entityID="pingidentity" xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata">
<md:IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"
WantAuthnRequestsSigned="false">
<md:KeyDescriptor use="signing">
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509Data>
<ds:X509Certificate>MIIDQD...q9kMuY=
</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</md:KeyDescriptor>
<md:KeyDescriptor use="encryption">
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509Data>
<ds:X509Certificate>MIID...q9kMuY=
</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</md:KeyDescriptor>
<md:ArtifactResolutionService index="0"
Location="https://xxxwm07.integration.company.at:9031/idp/ARS.ssaml2"
Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" isDefault="true" />
<md:SingleLogoutService
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
Location="https://xxxwm07.integration.company.at:9031/idp/SLO.saml2" />
<md:SingleLogoutService
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://xxxwm07.integration.company.at:9031/idp/SLO.saml2" />
<md:SingleLogoutService
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact"
Location="https://xxxwm07.integration.company.at:9031/idp/SLO.saml2" />
<md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP"
Location="https://xxxwm07.integration.company.at:9031/idp/SLO.ssaml2" />
<md:SingleSignOnService
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://xxxwm07.integration.company.at:9031/idp/SSO.saml2" />
<md:SingleSignOnService
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
Location="https://xxxwm07.integration.company.at:9031/idp/SSO.saml2" />
<md:SingleSignOnService
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact"
Location="https://xxxwm07.integration.company.at:9031/idp/SSO.saml2" />
<md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP"
Location="https://xxxwm07.integration.company.at:9031/idp/SSO.saml2" />
<saml:Attribute Name="subject"
NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" />
</md:IDPSSODescriptor>
<md:AttributeAuthorityDescriptor
protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<md:AttributeService
Location="https://xxxwm07.integration.company.at:9031/idp/attrsvc.ssaml2"
Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" />
</md:AttributeAuthorityDescriptor>
<md:ContactPerson contactType="administrative" />
**** sp.xml
<md:EntityDescriptor ID="U.NC.JbPpTmbfH8OQy8l9EhyRBl"
cacheDuration="PT1440M" entityID="app1" xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata">
<md:SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<md:KeyDescriptor use="signing">
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509Data>
<ds:X509Certificate>MIID....kMuY=
</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</md:KeyDescriptor>
<md:KeyDescriptor use="encryption">
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509Data>
<ds:X509Certificate>MIID....uY=
</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</md:KeyDescriptor>
<md:ArtifactResolutionService index="0"
Location="https://xxxwm07.integration.company.at:9031/sp/ARS.ssaml2"
Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" isDefault="true" />
<md:SingleLogoutService
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
Location="https://xxxwm07.integration.company.at:9031/sp/SLO.saml2" />
<md:SingleLogoutService
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://xxxwm07.integration.company.at:9031/sp/SLO.saml2" />
<md:SingleLogoutService
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact"
Location="https://xxxwm07.integration.company.at:9031/sp/SLO.saml2" />
<md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP"
Location="https://xxxwm07.integration.company.at:9031/sp/SLO.ssaml2" />
<md:AssertionConsumerService index="0"
Location="https://xxxwm07.integration.company.at:9031/sp/ACS.saml2"
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" isDefault="true" />
<md:AssertionConsumerService index="1"
Location="https://xxxwm07.integration.company.at:9031/sp/ACS.saml2"
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" />
<md:AssertionConsumerService index="2"
Location="https://xxxwm07.integration.company.at:9031/sp/ACS.saml2"
Binding="urn:oasis:names:tc:SAML:2.0:bindings:PAOS" />
<md:AttributeConsumingService index="0">
<md:ServiceName xml:lang="en">AttributeContract
</md:ServiceName>
<md:RequestedAttribute Name="subject" />
</md:AttributeConsumingService>
</md:SPSSODescriptor>
<md:ContactPerson contactType="administrative" />
*** here is the sp.xml solution generated from the sample application
<?xml version="1.0" encoding="UTF-8"?>
<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"
ID="app1" entityID="app1">
<md:SPSSODescriptor AuthnRequestsSigned="true"
WantAssertionsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<md:KeyDescriptor use="signing">
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509Data>
<ds:X509Certificate>MIIDQDCCAiigAwIBAg...wq9kMuY=
</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</md:KeyDescriptor>
<md:KeyDescriptor use="encryption">
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509Data>
<ds:X509Certificate>MIIDQDCCAiigAwIBAgIGAVzUOBXsMA0GCSqGSIb3DQEBCwUAMGExCzAJBgNVBAYTAkFUMSgwJgYD
VQQKEx9ldzd1aXB3bTA3LmludGVncmF0...q9kMuY=
</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</md:KeyDescriptor>
<md:SingleLogoutService
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
Location="https://host1:8443/app1/saml/SingleLogout" />
<md:SingleLogoutService
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
Location="https://host1:8443/app1/saml/SingleLogout" />
<md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress
</md:NameIDFormat>
<md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient
</md:NameIDFormat>
<md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent
</md:NameIDFormat>
<md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified
</md:NameIDFormat>
<md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName
</md:NameIDFormat>
<md:AssertionConsumerService
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://host1:8443/app1/saml/SSO"
index="0" isDefault="true" />
</md:SPSSODescriptor>
</md:EntityDescriptor>