title: Spring boot Spring ws security for soap based web service
body: <p>I have the following implementation in place for SOAP based web service and its security. </p>
  
  <pre><code>package com.hcentive.webservice.soap;
  
  import org.apache.log4j.Logger;
  import org.springframework.boot.context.embedded.ServletRegistrationBean;
  import org.springframework.context.ApplicationContext;
  import org.springframework.context.annotation.Bean;
  import org.springframework.context.annotation.Configuration;
  import org.springframework.context.annotation.ImportResource;
  import org.springframework.core.io.ClassPathResource;
  import org.springframework.ws.config.annotation.EnableWs;
  import org.springframework.ws.config.annotation.WsConfigurerAdapter;
  import org.springframework.ws.transport.http.MessageDispatcherServlet;
  import org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition;
  import org.springframework.xml.xsd.SimpleXsdSchema;
  import org.springframework.xml.xsd.XsdSchema;
  
  /**
   * @author Mebin.Jacob
   * Web service configuration class
   * @since 03-Sept-2014
   */
  @EnableWs
  @Configuration
  @ImportResource({"classpath:/spring-ws-servlet.xml","classpath:/security.xml"})
  public class WebServiceConfig extends WsConfigurerAdapter {
  
      Logger logger = Logger.getLogger(WebServiceConfig.class); 
  
      @Bean
      public ServletRegistrationBean dispatcherServlet(ApplicationContext applicationContext) {
          MessageDispatcherServlet servlet = new MessageDispatcherServlet();
          servlet.setApplicationContext(applicationContext);
          servlet.setTransformWsdlLocations(true);
          return new ServletRegistrationBean(servlet, "/ws/*");
      }
  
      @Bean(name = "coa_application_service")
      public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema coa_applicationSchema) {
          DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
          wsdl11Definition.setPortTypeName("FormsPort");
          wsdl11Definition.setLocationUri("/ws");
          wsdl11Definition.setTargetNamespace("http://hcentive.com/service");
          wsdl11Definition.setSchema(coa_applicationSchema);
          return wsdl11Definition;
      }
  
      /*@Bean
      public EmbeddedServletContainerFactory servletContainer(){
          TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory();
          logger.info("Setting context path ");
          factory.setContextPath("/spring-ws-servlet.xml");
          return factory;
      }
  */
      @Bean
      public XsdSchema coa_applicationSchema() {
          return new SimpleXsdSchema(new ClassPathResource("coa_application_service.xsd"));
      }
  }
  </code></pre>
  
  <p>//spring-ws-servlet.xml </p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="
      http://www.springframework.org/schema/beans 
      http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
      http://www.springframework.org/schema/security/spring-security-3.1.xsd"&gt;
  
  
      &lt;bean id="wsSecurityInterceptor"
          class="org.springframework.ws.soap.security.xwss.XwsSecurityInterceptor"&gt;
          &lt;property name="policyConfiguration" value="classpath:securityPolicy.xml" /&gt;
          &lt;property name="callbackHandlers"&gt;
              &lt;list&gt;
                  &lt;ref bean="keyStoreHandler" /&gt;
                  &lt;ref bean="springCertificateHandler" /&gt;
              &lt;/list&gt;
          &lt;/property&gt;
      &lt;/bean&gt;
      &lt;bean id="keyStoreHandler"
          class="org.springframework.ws.soap.security.xwss.callback.KeyStoreCallbackHandler"&gt;
          &lt;property name="keyStore" ref="keyStore" /&gt;
          &lt;property name="privateKeyPassword" value="changeit" /&gt;
      &lt;/bean&gt;
  
      &lt;bean id="keyStore"
          class="org.springframework.ws.soap.security.support.KeyStoreFactoryBean"&gt;
          &lt;property name="password" value="changeit" /&gt;
          &lt;property name="location" value="classpath:/keystore.jks" /&gt;
      &lt;/bean&gt;
  
  
      &lt;bean id="springCertificateHandler"
          class="org.springframework.ws.soap.security.xwss.callback.SpringCertificateValidationCallbackHandler"&gt;
          &lt;property name="authenticationManager"&gt;
              &lt;bean class="com.hcentive.security.SimpleAuthenticationManager" /&gt;
          &lt;/property&gt;
      &lt;/bean&gt;
  
  &lt;/beans&gt;
  </code></pre>
  
  <p>//security.xml</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;beans:beans xmlns="http://www.springframework.org/schema/security"
      xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.springframework.org/schema/beans
             http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
             http://www.springframework.org/schema/security
             http://www.springframework.org/schema/security/spring-security-3.2.xsd"&gt;
  
      &lt;http&gt;
          &lt;!-- Every user request needs to be authenticated and authorized --&gt;
          &lt;intercept-url pattern="/**" access="ROLE_USER"/&gt;
  
          &lt;!-- x509 Pre authentication - pull username from the Common Name 
              field of the client certificate and extract the last 'word', in our client 
              cert example, 'John Smith jsmith', the username 'jsmith' --&gt;
          &lt;x509 subject-principal-regex="CN=.*?\s(\w+)," /&gt;
  
          &lt;logout /&gt;
      &lt;/http&gt;
  
        &lt;authentication-manager&gt;
          &lt;authentication-provider&gt;
              &lt;user-service&gt;
                  &lt;user name="Jacob" 
                      authorities="ROLE_USER, ROLE_ADMIN" /&gt;
              &lt;/user-service&gt;
          &lt;/authentication-provider&gt;
      &lt;/authentication-manager&gt;
  
  
  &lt;/beans:beans&gt;
  </code></pre>
  
  <p>and this is what my logs shows :- </p>
  
  <pre><code>   Algorithm: [SHA256withRSA]
    Signature:
  0000: 48 85 7A CA A7 1D DC 13   D1 0D 3D EB 10 20 A8 0E  H.z.......=.. ..
  0010: 1D 2A 82 AF 0D 40 04 1A   4F 57 16 AF CF 2A 13 22  .*...@..OW...*."
  0020: 79 A4 EB 81 29 13 56 94   78 AF EF D6 BE 3C B2 1B  y...).V.x....&lt;..
  0030: 7C B2 CC B6 69 00 56 41   58 A1 E5 03 5A 27 5B 97  ....i.VAX...Z'[.
  0040: A5 49 8A 71 9C 78 13 0C   2D BC BD AE E5 26 52 9F  .I.q.x..-....&amp;R.
  0050: 8B EA 43 91 E0 DA 46 D2   15 C5 8B 23 E2 98 2E 9E  ..C...F....#....
  0060: 67 80 07 C1 94 76 E8 89   8F E6 10 D2 C4 3A 41 80  g....v.......:A.
  0070: A6 CA E9 59 4F A2 3C 6A   FB D9 71 C7 29 0A A1 83  ...YO.&lt;j..q.)...
  0080: D9 9E DE 09 F7 AC 18 EE   CE B2 A5 07 0C 0F C5 92  ................
  0090: A8 82 3D 61 10 00 5A EC   90 E9 E7 94 72 CA 93 AA  ..=a..Z.....r...
  00A0: 04 C3 83 61 4C 4D AD 08   D2 54 A8 96 58 5A 06 D3  ...aLM...T..XZ..
  00B0: C2 0F 52 24 B1 7A EF 7C   52 27 92 88 34 EE 44 83  ..R$.z..R'..4.D.
  00C0: E0 88 94 40 03 7A C3 7B   C8 D8 51 5A 0B 56 D3 22  ...@.z....QZ.V."
  00D0: 36 11 04 B1 C0 8C F7 B3   B3 7C 4C F1 FF A4 50 41  6.........L...PA
  00E0: 4A EE FC 2D 7C DE F2 54   3F 8A 38 B7 BF E3 6C 89  J..-...T?.8...l.
  00F0: D1 3D 34 55 F5 F9 10 4B   77 A9 36 BF 23 5E 87 B4  .=4U...Kw.6.#^..
  
  ]
  preAuthenticatedPrincipal = Jacob, trying to authenticate
  Authentication attempt using org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider
  PreAuthenticated authentication request: org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken@fbbdfcac: Principal: Jacob; Credentials: [PROTECTED]; Authenticated: false; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Not granted any authorities
  Authentication success: org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken@fcc8a5: Principal: org.springframework.security.core.userdetails.User@44064bf: Username: Jacob; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ADMIN,ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Granted Authorities: ROLE_ADMIN, ROLE_USER
  / at position 5 of 10 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
  / at position 6 of 10 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
  / at position 7 of 10 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
  SecurityContextHolder not populated with anonymous token, as it already contained: 'org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken@fcc8a5: Principal: org.springframework.security.core.userdetails.User@44064bf: Username: Jacob; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ADMIN,ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Granted Authorities: ROLE_ADMIN, ROLE_USER'
  / at position 8 of 10 in additional filter chain; firing Filter: 'SessionManagementFilter'
  Delegating to org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy@11664436
  HttpSession being created as SecurityContext is non-default
  SecurityContext stored to HttpSession: 'org.springframework.security.core.context.SecurityContextImpl@fcc8a5: Authentication: org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken@fcc8a5: Principal: org.springframework.security.core.userdetails.User@44064bf: Username: Jacob; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ADMIN,ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Granted Authorities: ROLE_ADMIN, ROLE_USER'
  / at position 9 of 10 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
  / at position 10 of 10 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
  Secure object: FilterInvocation: URL: /; Attributes: [ROLE_USER]
  Previously Authenticated: org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken@fcc8a5: Principal: org.springframework.security.core.userdetails.User@44064bf: Username: Jacob; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ADMIN,ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Granted Authorities: ROLE_ADMIN, ROLE_USER
  Voter: org.springframework.security.access.vote.RoleVoter@6290f34d, returned: 1
  Authorization successful
  RunAsManager did not change Authentication object
  / reached end of additional filter chain; proceeding with original chain
  SecurityContext stored to HttpSession: 'org.springframework.security.core.context.SecurityContextImpl@fcc8a5: Authentication: org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken@fcc8a5: Principal: org.springframework.security.core.userdetails.User@44064bf: Username: Jacob; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ADMIN,ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Granted Authorities: ROLE_ADMIN, ROLE_USER'
  Chain processed normally
  SecurityContextHolder now cleared, as request processing completed
  /error at position 1 of 10 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
  Obtained a valid SecurityContext from SPRING_SECURITY_CONTEXT: 'org.springframework.security.core.context.SecurityContextImpl@fcc8a5: Authentication: org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken@fcc8a5: Principal: org.springframework.security.core.userdetails.User@44064bf: Username: Jacob; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ADMIN,ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Granted Authorities: ROLE_ADMIN, ROLE_USER'
  /error at position 2 of 10 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
  /error at position 3 of 10 in additional filter chain; firing Filter: 'LogoutFilter'
  /error at position 4 of 10 in additional filter chain; firing Filter: 'X509AuthenticationFilter'
  Checking secure context token: org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken@fcc8a5: Principal: org.springframework.security.core.userdetails.User@44064bf: Username: Jacob; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ADMIN,ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Granted Authorities: ROLE_ADMIN, ROLE_USER
  /error at position 5 of 10 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
  /error at position 6 of 10 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
  /error at position 7 of 10 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
  SecurityContextHolder not populated with anonymous token, as it already contained: 'org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken@fcc8a5: Principal: org.springframework.security.core.userdetails.User@44064bf: Username: Jacob; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ADMIN,ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Granted Authorities: ROLE_ADMIN, ROLE_USER'
  /error at position 8 of 10 in additional filter chain; firing Filter: 'SessionManagementFilter'
  /error at position 9 of 10 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
  /error at position 10 of 10 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
  /error reached end of additional filter chain; proceeding with original chain
  Chain processed normally
  SecurityContextHolder now cleared, as request processing completed
  </code></pre>
  
  <p>The authorization and access seems to be fine or perhaps I misunderstand something?? But the request does not seem to be going forward to my SOAP endpoint. I am a newbee with spring ws, spring boot. Have been stuck with this for a while. ....</p>
  
  <p>Looks like after the loading of the filters the call to the messageDispatcherservlet is not made. Anyone any clue why that is not happening. I don't see any errors in my log!!! </p>
  
  <p>Thanks,
  Mebin</p>