Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring-SAML : Incoming SAML message is invalid

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.

like image 432
Jiten Avatar asked Nov 15 '16 21:11

Jiten


People also ask

What does the SAML message is invalid mean?

If, when signing in to Apps on Demand, you see a message that says "Your request included an invalid SAML response," it means you are not included in the group authorized for access to this class's stream.

How do I fix authentication failed on SAML?

Reconfigure IdP details in Service Provider and try again. Unable to process the Status Code received. There may be multiple reasons for this issue- Authentication failure in IdP or Time mismatch between IdP Server and SP Server. Mostly, Reconfigure the IdP and SP details in both IdP and SP should solve the issue.


2 Answers

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>
like image 124
Jiten Avatar answered Jan 02 '23 23:01

Jiten


A few problems I found in your securityContext.xml:

  1. entityId entity id does not need to point ot metadata. This is not a serious problem, but it's better to have your entity id more consice. It should be something like com:mycompany:my app. It is only used by IDP to identify your application.

  2. processUrl property of samlEntryPoint
    You have <property name="filterProcessesUrl" value="/saml/SSO"/> in your samlEntryPoint bean. samlEntryPoint is used when accessing /login, so you application can point you to your IDP's address. /SSO is used for when your IDP sends the message back to your application, and you application use this message to get authorization and information of the user from IDP.
    In the documentation, it says filterProcessesUrl is Url this filter should get activated on. But in your samlFilter bean you have already set samlEntryPoint on /login/**. So your setting is unnecessary and incorrect.

  3. failureRedirectHandler missing defaultFailureUrl property
    See example securityContext.xml for reference

  4. filter on pattern /saml/metadata should be metadataDisplayFilter
    You need to display your metadata when you access this page, and give this metadata to your IDP.

In all, I think it's the second point that causes the problem you have above, and it's the most sever problem you have. You should try to fix your securityContext.xml first and see if that works. If not, try use the example securityContext.xml with minimal modificaiton to make sure your applicatoin works, and then modify the file gradually to minimize risk of breaking.

like image 26
Alic Avatar answered Jan 02 '23 23:01

Alic