2
votes

I want to authenticate a user using openAm and share the session to communicate to other microservices without authenticating the user again. Session details are stored in an external database. I am using spring security saml sample application with all the java configuration to achieve this. There are two sessions being generated . One before logging to the IDP and one after entering the credentials. If I check at openAm, user is logged in but in the application, i am getting SAMLException specifying InResponseToField of the Response doesnt correspond to sent message 12345(random id). How to integrate spring session with saml?

Security config file of my sample application

package com.vdenotaris.spring.boot.security.saml.web.config;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private SAMLUserDetailsServiceImpl samlUserDetailsServiceImpl;


    @Bean
    public VelocityEngine velocityEngine() {
        return VelocityFactory.getEngine();
    }


    @Bean(initMethod = "initialize")
    public StaticBasicParserPool parserPool() {
        return new StaticBasicParserPool();
    }

    @Bean(name = "parserPoolHolder")
    public ParserPoolHolder parserPoolHolder() {
        return new ParserPoolHolder();
    }


    @Bean
    public MultiThreadedHttpConnectionManager multiThreadedHttpConnectionManager() {
        return new MultiThreadedHttpConnectionManager();
    }

    @Bean
    public HttpClient httpClient() {
        return new HttpClient(multiThreadedHttpConnectionManager());
    }     

    @Bean
    public SAMLAuthenticationProvider samlAuthenticationProvider() {
        SAMLAuthenticationProvider samlAuthenticationProvider = new SAMLAuthenticationProvider();
        samlAuthenticationProvider.setUserDetails(samlUserDetailsServiceImpl);
        samlAuthenticationProvider.setForcePrincipalAsString(false);
        return samlAuthenticationProvider;
    }     
  @Bean
    public SAMLContextProviderImpl contextProvider() {
        return new SAMLContextProviderImpl();
    }     

    @Bean
    public static SAMLBootstrap sAMLBootstrap() {
        return new SAMLBootstrap();
    }     

    @Bean
    public SAMLDefaultLogger samlLogger() {
        return new SAMLDefaultLogger();
    }
    @Bean
    public WebSSOProfileConsumer webSSOprofileConsumer() {
        return new WebSSOProfileConsumerImpl();
    }
    @Bean
    public WebSSOProfileConsumerHoKImpl hokWebSSOprofileConsumer() {
        return new WebSSOProfileConsumerHoKImpl();
    }
    @Bean
    public WebSSOProfile webSSOprofile() {
        return new WebSSOProfileImpl();
    }
    @Bean
    public WebSSOProfileConsumerHoKImpl hokWebSSOProfile() {
        return new WebSSOProfileConsumerHoKImpl();
    }
    @Bean
    public WebSSOProfileECPImpl ecpprofile() {
        return new WebSSOProfileECPImpl();
    }

    @Bean
    public SingleLogoutProfile logoutprofile() {
        return new SingleLogoutProfileImpl();
    }
    @Bean
    public KeyManager keyManager() {
        DefaultResourceLoader loader = new DefaultResourceLoader();
        Resource storeFile = loader
                .getResource("classpath:/saml/keystore.jks");
        String storePass = "password";
        Map<String, String> passwords = new HashMap<String, String>();
        passwords.put("mydomain", "password");
        String defaultKey = "mydomain";
        return new JKSKeyManager(storeFile, storePass, passwords, defaultKey);
    }
    @Bean
    public TLSProtocolConfigurer tlsProtocolConfigurer() {
      return new TLSProtocolConfigurer();
    }

    @Bean
    public ProtocolSocketFactory socketFactory() {
        return new TLSProtocolSocketFactory(keyManager(), null, "default");
    }

    @Bean
    public Protocol socketFactoryProtocol() {
        return new Protocol("https", socketFactory(), 443);
    }

    @Bean
    public MethodInvokingFactoryBean socketFactoryInitialization() {
        MethodInvokingFactoryBean methodInvokingFactoryBean = new MethodInvokingFactoryBean();
        methodInvokingFactoryBean.setTargetClass(Protocol.class);
        methodInvokingFactoryBean.setTargetMethod("registerProtocol");
        Object[] args = {"https", socketFactoryProtocol()};
        methodInvokingFactoryBean.setArguments(args);
        return methodInvokingFactoryBean;
    }

    @Bean
    public WebSSOProfileOptions defaultWebSSOProfileOptions() {
        WebSSOProfileOptions webSSOProfileOptions = new WebSSOProfileOptions();
        webSSOProfileOptions.setIncludeScoping(false);
        return webSSOProfileOptions;
    }

    // Entry point to initialize authentication, default values taken from
    // properties file
    @Bean
    public SAMLEntryPoint samlEntryPoint() {
        SAMLEntryPoint samlEntryPoint = new SAMLEntryPoint();
        samlEntryPoint.setDefaultProfileOptions(defaultWebSSOProfileOptions());
        return samlEntryPoint;
    }
    @Bean
    public ExtendedMetadata extendedMetadata() {
      ExtendedMetadata extendedMetadata = new ExtendedMetadata();
      extendedMetadata.setIdpDiscoveryEnabled(true); 
      extendedMetadata.setSignMetadata(false);
      return extendedMetadata;
    }

    @Bean
    public SAMLDiscovery samlIDPDiscovery() {
        SAMLDiscovery idpDiscovery = new SAMLDiscovery();        
        idpDiscovery.setIdpSelectionPath("/saml/idpSelection");
        return idpDiscovery;
    }

  @Bean
  @Qualifier("idp-ssocircle")
  public ExtendedMetadataDelegate ssoCircleExtendedMetadataProvider()
      throws MetadataProviderException {
    String idpSSOCircleMetadataURL = "http://openam.com:8080/OpenAM/saml2/jsp/exportmetadata.jsp";
    Timer backgroundTaskTimer = new Timer(true);
    HTTPMetadataProvider httpMetadataProvider = new HTTPMetadataProvider(
        backgroundTaskTimer, httpClient(), idpSSOCircleMetadataURL);
    httpMetadataProvider.setParserPool(parserPool());
    ExtendedMetadataDelegate extendedMetadataDelegate = 
        new ExtendedMetadataDelegate(httpMetadataProvider, extendedMetadata());
    extendedMetadataDelegate.setMetadataTrustCheck(true);
    extendedMetadataDelegate.setMetadataRequireSignature(false);
    return extendedMetadataDelegate;
  }
    @Bean
    @Qualifier("metadata")
    public CachingMetadataManager metadata() throws MetadataProviderException {
        List<MetadataProvider> providers = new ArrayList<MetadataProvider>();
        providers.add(ssoCircleExtendedMetadataProvider());
        return new CachingMetadataManager(providers);
    }

    // Filter automatically generates default SP metadata
    @Bean
    public MetadataGenerator metadataGenerator() {
        MetadataGenerator metadataGenerator = new MetadataGenerator();
        metadataGenerator.setEntityId("http://localhost:8080/spring-boot-security-saml2-sample/saml/web/metadata");
        metadataGenerator.setExtendedMetadata(extendedMetadata());
        metadataGenerator.setIncludeDiscoveryExtension(false);
        metadataGenerator.setKeyManager(keyManager()); 
        return metadataGenerator;
    }

    // The filter is waiting for connections on URL suffixed with filterSuffix
    // and presents SP metadata there
    @Bean
    public MetadataDisplayFilter metadataDisplayFilter() {
        return new MetadataDisplayFilter();
    }

    // Handler deciding where to redirect user after successful login
    @Bean
    public SavedRequestAwareAuthenticationSuccessHandler successRedirectHandler() {
        SavedRequestAwareAuthenticationSuccessHandler successRedirectHandler =
                new SavedRequestAwareAuthenticationSuccessHandler();
        successRedirectHandler.setDefaultTargetUrl("/");     
        return successRedirectHandler;
    }

  // Handler deciding where to redirect user after failed login
    @Bean
    public SimpleUrlAuthenticationFailureHandler authenticationFailureHandler() {
      SimpleUrlAuthenticationFailureHandler failureHandler =
          new SimpleUrlAuthenticationFailureHandler();
      failureHandler.setUseForward(true);
      failureHandler.setDefaultFailureUrl("/error");
      return failureHandler;
    }

    @Bean
    public SAMLWebSSOHoKProcessingFilter samlWebSSOHoKProcessingFilter() throws Exception {
        SAMLWebSSOHoKProcessingFilter samlWebSSOHoKProcessingFilter = new SAMLWebSSOHoKProcessingFilter();
        samlWebSSOHoKProcessingFilter.setAuthenticationSuccessHandler(successRedirectHandler());
        samlWebSSOHoKProcessingFilter.setAuthenticationManager(authenticationManager());
        samlWebSSOHoKProcessingFilter.setAuthenticationFailureHandler(authenticationFailureHandler());
        return samlWebSSOHoKProcessingFilter;
    }
    @Bean
    public SAMLProcessingFilter samlWebSSOProcessingFilter() throws Exception {
        SAMLProcessingFilter samlWebSSOProcessingFilter = new SAMLProcessingFilter();
        samlWebSSOProcessingFilter.setAuthenticationManager(authenticationManager());
        samlWebSSOProcessingFilter.setAuthenticationSuccessHandler(successRedirectHandler());
        samlWebSSOProcessingFilter.setAuthenticationFailureHandler(authenticationFailureHandler());
        return samlWebSSOProcessingFilter;
    }

    @Bean
    public MetadataGeneratorFilter metadataGeneratorFilter() {
        return new MetadataGeneratorFilter(metadataGenerator());
    }
    @Bean
    public SimpleUrlLogoutSuccessHandler successLogoutHandler() {
        SimpleUrlLogoutSuccessHandler successLogoutHandler = new SimpleUrlLogoutSuccessHandler();
        successLogoutHandler.setDefaultTargetUrl("/");
        return successLogoutHandler;
    }
    @Bean
    public SecurityContextLogoutHandler logoutHandler() {
        SecurityContextLogoutHandler logoutHandler = 
            new SecurityContextLogoutHandler();
        logoutHandler.setInvalidateHttpSession(true);
        logoutHandler.setClearAuthentication(true);
        return logoutHandler;
    }

    @Bean
    public SAMLLogoutProcessingFilter samlLogoutProcessingFilter() {
        return new SAMLLogoutProcessingFilter(successLogoutHandler(),
                logoutHandler());
    }         
    @Bean
    public SAMLLogoutFilter samlLogoutFilter() {
        return new SAMLLogoutFilter(successLogoutHandler(),
                new LogoutHandler[] { logoutHandler() },
                new LogoutHandler[] { logoutHandler() });
    }

    private ArtifactResolutionProfile artifactResolutionProfile() {
        final ArtifactResolutionProfileImpl artifactResolutionProfile = 
            new ArtifactResolutionProfileImpl(httpClient());
        artifactResolutionProfile.setProcessor(new SAMLProcessorImpl(soapBinding()));
        return artifactResolutionProfile;
    }

    @Bean
    public HTTPArtifactBinding artifactBinding(ParserPool parserPool, VelocityEngine velocityEngine) {
        return new HTTPArtifactBinding(parserPool, velocityEngine, artifactResolutionProfile());
    }

    @Bean
    public HTTPSOAP11Binding soapBinding() {
        return new HTTPSOAP11Binding(parserPool());
    }

    @Bean
    public HTTPPostBinding httpPostBinding() {
      return new HTTPPostBinding(parserPool(), velocityEngine());
    }

    @Bean
    public HTTPRedirectDeflateBinding httpRedirectDeflateBinding() {
      return new HTTPRedirectDeflateBinding(parserPool());
    }

    @Bean
    public HTTPSOAP11Binding httpSOAP11Binding() {
      return new HTTPSOAP11Binding(parserPool());
    }

    @Bean
    public HTTPPAOS11Binding httpPAOS11Binding() {
      return new HTTPPAOS11Binding(parserPool());
    }

    // Processor
  @Bean
  public SAMLProcessorImpl processor() {
    Collection<SAMLBinding> bindings = new ArrayList<SAMLBinding>();
    bindings.add(httpRedirectDeflateBinding());
    bindings.add(httpPostBinding());
    bindings.add(artifactBinding(parserPool(), velocityEngine()));
    bindings.add(httpSOAP11Binding());
    bindings.add(httpPAOS11Binding());
    return new SAMLProcessorImpl(bindings);
  }
    @Bean
    public FilterChainProxy samlFilter() throws Exception {
        List<SecurityFilterChain> chains = new ArrayList<SecurityFilterChain>();
        chains.add(new DefaultSecurityFilterChain(new AntPathRequestMatcher("/saml/login/**"),
                samlEntryPoint()));
        chains.add(new DefaultSecurityFilterChain(new AntPathRequestMatcher("/saml/logout/**"),
                samlLogoutFilter()));
        chains.add(new DefaultSecurityFilterChain(new AntPathRequestMatcher("/saml/metadata/**"),
                metadataDisplayFilter()));
        chains.add(new DefaultSecurityFilterChain(new AntPathRequestMatcher("/saml/SSO/**"),
                samlWebSSOProcessingFilter()));
        chains.add(new DefaultSecurityFilterChain(new AntPathRequestMatcher("/saml/SSOHoK/**"),
                samlWebSSOHoKProcessingFilter()));
        chains.add(new DefaultSecurityFilterChain(new AntPathRequestMatcher("/saml/SingleLogout/**"),
                samlLogoutProcessingFilter()));
        chains.add(new DefaultSecurityFilterChain(new AntPathRequestMatcher("/saml/discovery/**"),
                samlIDPDiscovery()));
        return new FilterChainProxy(chains);
    }
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }


    @Override  
    protected void configure(HttpSecurity http) throws Exception {
        http
            .httpBasic()
                .authenticationEntryPoint(samlEntryPoint());
        http
          .csrf()
            .disable();
        http
            .addFilterBefore(metadataGeneratorFilter(), ChannelProcessingFilter.class)
            .addFilterAfter(samlFilter(), BasicAuthenticationFilter.class)
            .addFilterBefore(sessionRepositoryFilter(sessionRepository(), httpSessionStrategy()),
                ChannelProcessingFilter.class)
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
        http        
            .authorizeRequests()
            .antMatchers("/").permitAll()
            .antMatchers("/publicUrl").permitAll()
            .antMatchers("/app/**").permitAll()
            .antMatchers("/error").permitAll()
            .antMatchers("/saml/**").permitAll()
            .antMatchers("/landing").authenticated();

        http
            .logout()
                .logoutSuccessUrl("/");
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .authenticationProvider(samlAuthenticationProvider());
    } 

    @Bean
    public HttpSessionStrategy httpSessionStrategy() 
    {
        return new HeaderHttpSessionStrategy();
    }    

    @Bean
    public SessionRepositoryFilter<ExpiringSession> sessionRepositoryFilter(
                    SessionRepository<ExpiringSession> sessionRepository, HttpSessionStrategy httpSessionStrategy) 
    {
        SessionRepositoryFilter<ExpiringSession> sessionRepositoryFilter = new SessionRepositoryFilter<>(
                        sessionRepository);
        sessionRepositoryFilter.setHttpSessionStrategy(httpSessionStrategy);
        return sessionRepositoryFilter;
    }

    @Bean
    public SessionRepository<ExpiringSession> sessionRepository() 
    {
        return new JPASessionRepository(1800);
    }    
}

JPA Session repository which implements SessionRepository is :

  package com.security.repositories.session;
    public class JPASessionRepository implements SessionRepository<ExpiringSession> 
    {

        private static final Logger LOG = LogManager.getLogger(JPASessionRepository.class);

        private int maxInactiveInterval = -1;

        @Autowired
        private SpringSessionRepository springSessionRepository;

        public JPASessionRepository() 
        {            
        }
        public JPASessionRepository(int maxInactiveInterval) 
        {
            this.maxInactiveInterval = maxInactiveInterval;
        }    
        @Override
        public ExpiringSession createSession() 
        {
            ExpiringSession result = new MapSession();
            result.setMaxInactiveIntervalInSeconds(maxInactiveInterval);
            return result;
        }   

        @Transactional
        @Override
        public void save(ExpiringSession session) 
        {
            springSessionRepository.save(convertToDomain(session));
        }

        @Transactional
        @Override
        public ExpiringSession getSession(String id) 
        {
            SessionEntity sessionEntity = springSessionRepository.findOne(id);
            ExpiringSession saved = null;
            if(sessionEntity != null)
            {
                saved = convertToSession(sessionEntity);
            }

            if (saved == null) 
            {
                return null;
            }
            if (saved.isExpired()) 
            {
                delete(saved.getId());
                return null;
            }
            return saved;
        }   
        @Override
        public void delete(String id) 
        {
            SessionEntity currentSession = springSessionRepository.findOne(id);
            if (null != currentSession) 
            {
                springSessionRepository.delete(id);
            }
        }
        private SessionEntity convertToDomain(ExpiringSession session) 
        {
            SessionEntity sessionEntity = new SessionEntity();
            sessionEntity.setId(session.getId());
            sessionEntity.setLastAccessedTime(session.getLastAccessedTime());
            sessionEntity.setCreationTime(session.getCreationTime());
            sessionEntity.setData(serializeAttributes(session));
            return sessionEntity;
        }
         byte[] serializeAttributes(ExpiringSession session) 
        {
            Map<String, Object> attributes = new HashMap<>();
            for (String attrName : session.getAttributeNames()) 
            {
                attributes.put(attrName, session.getAttribute(attrName));

            }
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            byte[] buffer;
            try 
            {
                ObjectOutputStream objectOutputStream = new ObjectOutputStream(out);
                objectOutputStream.writeObject(new SessionAttributes(attributes));
                buffer = out.toByteArray();
                objectOutputStream.close();
            } 
            catch (IOException e) 
            {
                throw new RuntimeException(e);
            }

            return buffer;
        }    

        private ExpiringSession convertToSession(SessionEntity sessionEntity) 
        {
            MapSession mapSession = new MapSession();
            mapSession.setId(sessionEntity.getId());
            mapSession.setLastAccessedTime(sessionEntity.getLastAccessedTime());
            mapSession.setCreationTime(sessionEntity.getCreationTime());
            mapSession.setMaxInactiveIntervalInSeconds(this.maxInactiveInterval);

            SessionAttributes attributes = deserializeAttributes(sessionEntity);
            if (attributes != null) 
            {
                for (Map.Entry<String, Object> attribute : attributes.getAttributes().entrySet()) 
                {
                    mapSession.setAttribute(attribute.getKey(), attribute.getValue());
                }
            }
            return mapSession;
        }       
        private SessionAttributes deserializeAttributes(SessionEntity sessionEntity) 
        {
            SessionAttributes attributes = null;
            if (sessionEntity.getData() != null && sessionEntity.getData().length > 0) 
            {
                try 
                {
                    ObjectInputStream objectInputStream = new ObjectInputStream(
                                    new ByteArrayInputStream(sessionEntity.getData()));

                    Object obj = objectInputStream.readObject();                    

                    attributes = (SessionAttributes) obj;
                    objectInputStream.close();
                } 
                catch (IOException | ClassNotFoundException e) 
                {
                    LOG.warn(e);
                    //FIXME:How should this exception be handled?
                }
            }
            return attributes;
        }    

        public Integer getDefaultMaxInactiveInterval() 
        {
            return maxInactiveInterval;
        }    
        public void setDefaultMaxInactiveInterval(int maxInactiveInterval) 
        {
            this.maxInactiveInterval = maxInactiveInterval;
        }    

        public SpringSessionRepository getSpringSessionRepository() 
        {
            return springSessionRepository;
        }    
        public void setSpringSessionRepository(SpringSessionRepository springSessionRepository) 
        {
            this.springSessionRepository = springSessionRepository;
        }
    }

SP Metadata

 <?xml version="1.0" encoding="UTF-8"?><md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" ID="http___localhost_8080_spring-boot-security-saml2-sample_saml_web_metadata" entityID="http://localhost:8080/spring-boot-security-saml2-sample/saml/web/metadata"><md:SPSSODescriptor AuthnRequestsSigned="true" WantAssertionsSigned="true" 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>x509 certificate data</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>--x509 certificate</ds:X509Certificate></ds:X509Data></ds:KeyInfo></md:KeyDescriptor><md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://localhost:8080/saml/SingleLogout"/><md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="http://localhost:8080/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="http://localhost:8080/saml/SSO" index="0" isDefault="true"/><md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" Location="http://localhost:8080/saml/SSO" index="1"/></md:SPSSODescriptor></md:EntityDescriptor>

IDP metadata:-

    <EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" entityID="http://localhost:8081/OpenAM">
    <IDPSSODescriptor WantAuthnRequestsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
    <KeyDescriptor use="signing">
    <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
    <ds:X509Data>
    <ds:X509Certificate>
   sample certificate
    </ds:X509Certificate>
    </ds:X509Data>
    </ds:KeyInfo>
    </KeyDescriptor>
    <ArtifactResolutionService index="0" isDefault="true" Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="http://localhost:8081/OpenAM/ArtifactResolver/metaAlias/idp"/>
    <SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="http://localhost:8081/OpenAM/IDPSloRedirect/metaAlias/idp" ResponseLocation="http://localhost:8081/OpenAM/IDPSloRedirect/metaAlias/idp"/>
    <SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://localhost:8081/OpenAM/IDPSloPOST/metaAlias/idp" ResponseLocation="http://localhost:8081/OpenAM/IDPSloPOST/metaAlias/idp"/>
    <SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="http://localhost:8081/OpenAM/IDPSloSoap/metaAlias/idp"/>
    <ManageNameIDService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="http://localhost:8081/OpenAM/IDPMniRedirect/metaAlias/idp" ResponseLocation="http://localhost:8081/OpenAM/IDPMniRedirect/metaAlias/idp"/>
    <ManageNameIDService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://localhost:8081/OpenAM/IDPMniPOST/metaAlias/idp" ResponseLocation="http://localhost:8081/OpenAM/IDPMniPOST/metaAlias/idp"/>
    <ManageNameIDService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="http://localhost:8081/OpenAM/IDPMniSoap/metaAlias/idp"/>
    <NameIDFormat>
    urn:oasis:names:tc:SAML:2.0:nameid-format:persistent
    </NameIDFormat>
    <NameIDFormat>
    urn:oasis:names:tc:SAML:2.0:nameid-format:transient
    </NameIDFormat>
    <NameIDFormat>
    urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress
    </NameIDFormat>
    <NameIDFormat>
    urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified
    </NameIDFormat>
    <NameIDFormat>
    urn:oasis:names:tc:SAML:1.1:nameid-format:WindowsDomainQualifiedName
    </NameIDFormat>
    <NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:kerberos</NameIDFormat>
    <NameIDFormat>
    urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName
    </NameIDFormat>
    <SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="http://localhost:8081/OpenAM/SSORedirect/metaAlias/idp"/>
    <SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://localhost:8081/OpenAM/SSOPOST/metaAlias/idp"/>
    <SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="http://localhost:8081/OpenAM/SSOSoap/metaAlias/idp"/>
    <NameIDMappingService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="http://localhost:8081/OpenAM/NIMSoap/metaAlias/idp"/>
    <AssertionIDRequestService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="http://localhost:8081/OpenAM/AIDReqSoap/IDPRole/metaAlias/idp"/>
    <AssertionIDRequestService Binding="urn:oasis:names:tc:SAML:2.0:bindings:URI" Location="http://localhost:8081/OpenAM/AIDReqUri/IDPRole/metaAlias/idp"/>
    </IDPSSODescriptor>
    </EntityDescriptor>

Please help me resolve the issue

1
Please post your IDP and SP metadata.blur0224
@blur0224 updated the SP and IDP metadataPrachi Gupta
Have you checked this out? github.com/ulisesbocchio/spring-boot-security-saml. Makes config easier between Spring Boot and SAMLUlises

1 Answers

2
votes

This error is usually caused by a mismatch of the EntityIDs in some way. It looks like your metadata is configured correctly, so I did some looking and found this.

Make sure that application uses the same HttpSession during sending of the request and reception of the response. Typically, this problem arises when the auhentication request is initialized from localhost address or http scheme, while response is received at a public host name or https scheme. E.g., when initializing authentication from URL https://host:port/app/saml/login, the response must be received at https://host;port/app/saml/SSO, not http://host:port/app/saml/SSO or https://localhost:port/app/saml/SSO.

The checking of the InResponseToField can be disabled by re-configuring the context provider as follows:

<bean id="contextProvider" class="org.springframework.security.saml.context.SAMLContextProviderImpl">
  <property name="storageFactory">
    <bean class="org.springframework.security.saml.storage.EmptyStorageFactory"/>
  </property>
</bean>

You should note that this should only be used for development purposes. You should probably use Spring Profiles to enable this configuration locally only because it's less secure.