Spring Security SAML Sample App is not working for me when I integrate it with PingIdentity. After getting the redirect to idp, loggin on Ping ok, getting a good saml assertion, get redirect back to Spring Security Sample SAML app, I get an endless loop with an access denied error in the spring-security stack. And an org.sourceid error in Ping. Error in Ping log is (right before creating a good SAML Assertion):
org.sourceid.saml20.profiles.StatusResponseException: Unknown AssertionConsumerServiceURL https://xxxwm07.integration.company.at:9031/sp/ACS.saml2
Access denied error in Spring is:
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 am about to go back to debug spring security, but if you have any tips, would be awesome. as you can see in this spring sec log, all looks ok with ping, the role voter is ok, then the authenticated user voter fails. and why do I end up with anonymousUser after a good ping authentication? seems some user principle needs to be mapped from ping to spring, yes?
If only a tip on where to start in my Spring Security debug, would be quite helpful...
Thanks in advance
Both IdP and SP config in Spring SAML Sample app are file based. Here are the details:
*******securityConext.xml
<bean id="metadata"
class="org.springframework.security.saml.metadata.CachingMetadataManager">
<constructor-arg>
<list>
<!-- IDP Metadata configuration -->
<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>
<!-- SP Metadata configuration -->
<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>
<!-- OPTIONAL used when one of the metadata files contains information
about this service provider -->
<!-- <property name="hostedSPName" value=""/> -->
<!-- OPTIONAL property: can tell the system which IDP should be used for
authenticating user by default. -->
<!-- <property name="defaultIDP" value="http://localhost:8080/opensso"/> -->
</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 solution sp.xml generated from sample app
<?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>