I am facing an issue while integrating my app with SAML.
The following is my error:
org.springframework.security.saml.SAMLProcessingFilter.attemptAuthentication: Incoming SAML message is invalid
org.opensaml.common.SAMLException: Endpoint with message binding urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST and URL https://myappruldotom/saml/SSO wasn't found in local metadata at org.springframework.security.saml.util.SAMLUtil.getEndpoint(SAMLUtil.java:357) ~[spring-security-saml2-core-1.0.2.RELEASE.jar:1.0.2.RELEASE]
My app is deployed on AWS and when i added the log statement in by writing the custom SAMLProcessingFilter and wrote implementation of getEndpoint() to add multiple log statements and copied the exact content of getEndpoint() method.
The log statement shows that the endpoint is coming as IP address : MySAMLProcessingFilter.getEndpoint: MySAMLLOG - endpoint.getLocation() = https://10.193.160.123:443/mysamlapp/saml/SSO
I have defined entityId in my SAML config, but this also didn't help. entityId in my config file as :
<bean id="metadataGeneratorFilter" class="org.springframework.security.saml.metadata.MetadataGeneratorFilter">
<constructor-arg>
<bean class="org.springframework.security.saml.metadata.MetadataGenerator">
<property name="entityId" value="https://myappruldotom/mysamlapp/saml/metadata"/>
<property name="requestSigned" value="false"/>
</bean>
</constructor-arg>
</bean>
securityContext.xml file :
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
<!-- ############################ Security Settings ############################ -->
<!-- Enable auto-wiring -->
<context:annotation-config/>
<!-- Scan for auto-wiring classes in spring saml packages -->
<context:component-scan base-package="org.springframework.security.saml"/>
<!-- IMPORTANT!! This entry is required to enable method-level security. -->
<security:global-method-security pre-post-annotations="enabled"></security:global-method-security>
<!-- No security on resource files -->
<security:http security="none" pattern="/resources/**" />
<!-- Secured pages with SAML as entry point with SPRING CSRF filter -->
<security:http entry-point-ref="samlEntryPoint" disable-url-rewriting="true" use-expressions="true">
<security:csrf disabled="true"/>
<security:intercept-url pattern="/cart/**" access="isAuthenticated()"/>
<security:custom-filter before="FIRST" ref="metadataGeneratorFilter"/>
<security:custom-filter after="BASIC_AUTH_FILTER" ref="samlFilter"/>
</security:http>
<!-- Filters for processing of SAML messages -->
<bean id="samlFilter" class="org.springframework.security.web.FilterChainProxy">
<security:filter-chain-map request-matcher="ant">
<security:filter-chain pattern="/saml/metadata/**" filters="metadataGeneratorFilter"/>
<security:filter-chain pattern="/login/**" filters="samlEntryPoint"/>
<security:filter-chain pattern="/saml/logout/**" filters="samlLogoutFilter"/>
<security:filter-chain pattern="/saml/SSO/**" filters="samlWebSSOProcessingFilter"/>
<security:filter-chain pattern="/saml/discovery/**" filters="samlIDPDiscovery"/>
<security:filter-chain pattern="/saml/SingleLogout/**" filters="samlLogoutProcessingFilter"/>
</security:filter-chain-map>
</bean>
<bean id="successRedirectHandler" class="org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler">
<property name="defaultTargetUrl" value="/cart"/>
</bean>
<!-- After logout, show the logout success page -->
<bean id="successLogoutHandler" class="org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler">
<property name="defaultTargetUrl" value="/"/>
</bean>
<!-- Logout handler terminating local session -->
<bean id="logoutHandler" class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler">
<property name="invalidateHttpSession" value="true"/>
</bean>
<!-- Handler deciding where to redirect user after failed login -->
<bean id="failureRedirectHandler" class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
<property name="useForward" value="true"/>
</bean>
<security:authentication-manager alias="authenticationManager">
<!-- Register authentication manager for SAML provider -->
<security:authentication-provider ref="samlAuthenticationProvider"/>
</security:authentication-manager>
<!-- Central storage of cryptographic keys -->
<bean id="keyManager" class="org.springframework.security.saml.key.JKSKeyManager">
<constructor-arg value="classpath: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>
<!-- Logger for SAML messages and events -->
<bean id="samlLogger" class="org.springframework.security.saml.log.SAMLDefaultLogger"/>
<!-- IDP Discovery Service -->
<bean id="samlIDPDiscovery" class="org.springframework.security.saml.SAMLDiscovery"></bean>
<bean id="metadataGeneratorFilter" class="org.springframework.security.saml.metadata.MetadataGeneratorFilter">
<constructor-arg>
<bean class="org.springframework.security.saml.metadata.MetadataGenerator">
<property name="entityId" value="https://myappdotcom/mysamlapp/saml/metadata"/>
<property name="requestSigned" value="false"/>
</bean>
</constructor-arg>
</bean>
<!-- Entry point to initialize authentication, default values taken from properties file -->
<bean id="samlEntryPoint" class="org.springframework.security.saml.SAMLEntryPoint">
<property name="filterProcessesUrl" value="/saml/SSO"/>
<property name="defaultProfileOptions">
<bean class="org.springframework.security.saml.websso.WebSSOProfileOptions">
<property name="includeScoping" value="false"/>
</bean>
</property>
</bean>
<bean id="metadata" class="org.springframework.security.saml.metadata.CachingMetadataManager">
<property name="defaultIDP" value="https://dev-942345.oktapreview.com/"/>
<constructor-arg>
<list>
<bean class="org.opensaml.saml2.metadata.provider.FilesystemMetadataProvider">
<constructor-arg>
<value type="java.io.File">#{systemProperties['catalina.home']}/saml/idp.xml</value>
</constructor-arg>
<property name="parserPool" ref="parserPool"/>
</bean>
</list>
</constructor-arg>
</bean>
<!-- SAML Authentication Provider responsible for validating of received SAML messages -->
<bean id="samlAuthenticationProvider" class="org.springframework.security.saml.SAMLAuthenticationProvider">
<property name="userDetails" ref="samlUserDetailsService" />
<property name="forcePrincipalAsString" value="false" />
</bean>
<!-- Custom user details service to attach app specific roles to federated identities -->
<bean id="samlUserDetailsService" class="com.zap.shop.SAMLUserDetailsServiceImpl"></bean>
<!-- Provider of default SAML Context -->
<bean id="contextProvider" class="org.springframework.security.saml.context.SAMLContextProviderImpl"/>
<!-- Processing filter for WebSSO profile messages -->
<bean id="samlWebSSOProcessingFilter" class="org.springframework.security.saml.SAMLProcessingFilter">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="authenticationSuccessHandler" ref="successRedirectHandler"/>
<property name="authenticationFailureHandler" ref="failureRedirectHandler"/>
</bean>
<!-- Override default logout processing filter with the one processing SAML messages -->
<bean id="samlLogoutFilter" class="org.springframework.security.saml.SAMLLogoutFilter">
<constructor-arg index="0" ref="successLogoutHandler"/>
<constructor-arg index="1" ref="logoutHandler"/>
<constructor-arg index="2" ref="logoutHandler"/>
</bean>
<!-- Filter processing incoming logout messages -->
<!-- First argument determines URL user will be redirected to after successful global logout -->
<bean id="samlLogoutProcessingFilter" class="org.springframework.security.saml.SAMLLogoutProcessingFilter">
<constructor-arg index="0" ref="successLogoutHandler"/>
<constructor-arg index="1" ref="logoutHandler"/>
</bean>
<!-- Class loading incoming SAML messages from httpRequest stream -->
<bean id="processor" class="org.springframework.security.saml.processor.SAMLProcessorImpl">
<constructor-arg>
<list>
<ref bean="redirectBinding"/>
<ref bean="postBinding"/>
<ref bean="artifactBinding"/>
<ref bean="soapBinding"/>
<ref bean="paosBinding"/>
</list>
</constructor-arg>
</bean>
<!-- SAML 2.0 WebSSO Assertion Consumer -->
<bean id="webSSOprofileConsumer" class="org.springframework.security.saml.websso.WebSSOProfileConsumerImpl"/>
<!-- SAML 2.0 Holder-of-Key WebSSO Assertion Consumer -->
<bean id="hokWebSSOprofileConsumer" class="org.springframework.security.saml.websso.WebSSOProfileConsumerHoKImpl"/>
<!-- SAML 2.0 Web SSO profile -->
<bean id="webSSOprofile" class="org.springframework.security.saml.websso.WebSSOProfileImpl"/>
<!-- SAML 2.0 Holder-of-Key Web SSO profile -->
<bean id="hokWebSSOProfile" class="org.springframework.security.saml.websso.WebSSOProfileConsumerHoKImpl"/>
<!-- SAML 2.0 ECP profile -->
<bean id="ecpprofile" class="org.springframework.security.saml.websso.WebSSOProfileECPImpl"/>
<!-- SAML 2.0 Logout Profile -->
<bean id="logoutprofile" class="org.springframework.security.saml.websso.SingleLogoutProfileImpl"/>
<!-- Bindings, encoders and decoders used for creating and parsing messages -->
<bean id="postBinding" class="org.springframework.security.saml.processor.HTTPPostBinding">
<constructor-arg ref="parserPool"/>
<constructor-arg ref="velocityEngine"/>
</bean>
<bean id="redirectBinding" class="org.springframework.security.saml.processor.HTTPRedirectDeflateBinding">
<constructor-arg ref="parserPool"/>
</bean>
<bean id="artifactBinding" class="org.springframework.security.saml.processor.HTTPArtifactBinding">
<constructor-arg ref="parserPool"/>
<constructor-arg ref="velocityEngine"/>
<constructor-arg>
<bean class="org.springframework.security.saml.websso.ArtifactResolutionProfileImpl">
<constructor-arg>
<bean class="org.apache.commons.httpclient.HttpClient">
<constructor-arg>
<bean class="org.apache.commons.httpclient.MultiThreadedHttpConnectionManager"/>
</constructor-arg>
</bean>
</constructor-arg>
<property name="processor">
<bean class="org.springframework.security.saml.processor.SAMLProcessorImpl">
<constructor-arg ref="soapBinding"/>
</bean>
</property>
</bean>
</constructor-arg>
</bean>
<bean id="soapBinding" class="org.springframework.security.saml.processor.HTTPSOAP11Binding">
<constructor-arg ref="parserPool"/>
</bean>
<bean id="paosBinding" class="org.springframework.security.saml.processor.HTTPPAOS11Binding">
<constructor-arg ref="parserPool"/>
</bean>
<!-- Initialization of OpenSAML library-->
<bean class="org.springframework.security.saml.SAMLBootstrap"/>
<!-- Initialization of the velocity engine -->
<bean id="velocityEngine" class="org.springframework.security.saml.util.VelocityFactory" factory-method="getEngine"/>
<!-- XML parser pool needed for OpenSAML parsing -->
<bean id="parserPool" class="org.opensaml.xml.parse.StaticBasicParserPool" init-method="initialize">
<property name="builderFeatures">
<map>
<entry key="http://xml.org/sax/features/external-general-entities" value="false"/>
<entry key="http://javax.xml.XMLConstants/feature/secure-processing" value="true"/>
<entry key="http://apache.org/xml/features/disallow-doctype-decl" value="true"/>
</map>
</property>
</bean>
<bean id="parserPoolHolder" class="org.springframework.security.saml.parser.ParserPoolHolder"/>
</beans>
Thanks for your help in advance.
To fix this issue, set the enityBaseURL property of MetadataGenerator inside metadataGeneratorFilter bean. Code looks like this :
<bean id="metadataGeneratorFilter" class="org.springframework.security.saml.metadata.MetadataGeneratorFilter">
<constructor-arg>
<bean class="org.springframework.security.saml.metadata.MetadataGenerator">
<property name="entityId" value="http://myapp.com/myapp/saml/metadata"/>
<property name="requestSigned" value="false"/>
<property name="entityBaseURL" value="http://myapp.com/myapp"/>
</bean>
</constructor-arg>
</bean>