Google chrome has introduced changes that require setting the Same-Site header. In order to achieve this, I added a custom filter as follows,
public class SameSiteFilter extends GenericFilterBean { private Logger LOG = LoggerFactory.getLogger(SameSiteFilter.class); @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletResponse resp = (HttpServletResponse)response; response = addSameSiteCookieAttribute((HttpServletResponse) response); chain.doFilter(request, response); } private HttpServletResponse addSameSiteCookieAttribute(HttpServletResponse response) { Collection<String> header = response.getHeaders(HttpHeaders.SET_COOKIE); LOG.info(String.format("%s; %s", header, "SameSite=None; Secure")); response.setHeader(HttpHeaders.SET_COOKIE, String.format("%s; %s", header, "SameSite=None; Secure")); return response; } }
Following is the code for Security Configuration
@Configuration @EnableWebMvcSecurity public class CustomSecurityConfiguration extends WebSecurityConfigurerAdapter { @Autowired private OnyxUserDetailsService onyxUserDetailsService; @Autowired private CustomAuthenticationProvider customAuthenticationProvider; @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests().antMatchers("/rest/user", "/info/**/*","/rest/version/check") .permitAll().antMatchers("/data/**/*") .access("hasRole('ROLE_ADMIN')").anyRequest() .fullyAuthenticated().and().httpBasic().realmName("ADOBENET") .and().logout(). logoutSuccessHandler((new LogoutSuccessHandler() { @Override public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { response.setStatus(HttpStatus.OK.value()); response.getWriter().flush(); } })).deleteCookies("JSESSIONID", "XSRF-TOKEN") .invalidateHttpSession(true).logoutUrl("/rest/logout") .logoutSuccessUrl("/rest/user").and() .addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class) .addFilterAfter(new SameSiteFilter(), BasicAuthenticationFilter.class) .csrf().disable(); } @Override @Order(Ordered.HIGHEST_PRECEDENCE) protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.authenticationProvider(customAuthenticationProvider); } }
However, when I look at the headers received, I get this
The filter adds the required fields in all the responses exception the one containing the JSESSIONID cookie. How do I add the headers to this cookie. I tried configuring tomcat settings, but we deploy the code as a WAR file, so that did also not work.
Advertisement
Answer
In order to get around this problem, I added a Filter for sifting through all the responses. Here is the code for the same,
@Component public class SameSiteFilter implements Filter { private Logger LOG = LoggerFactory.getLogger(SameSiteFilter.class); @Override public void init(final FilterConfig filterConfig) throws ServletException { LOG.info("Same Site Filter Initializing filter :{}", this); } @Override public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse res = (HttpServletResponse) response; LOG.info("Same Site Filter Logging Response :{}", res.getContentType()); Collection<String> headers = res.getHeaders(HttpHeaders.SET_COOKIE); boolean firstHeader = true; for (String header : headers) { // there can be multiple Set-Cookie attributes if (firstHeader) { res.setHeader(HttpHeaders.SET_COOKIE, String.format("%s; %s", header, "SameSite=None")); LOG.info(String.format("Same Site Filter First Header %s; %s", header, "SameSite=None; Secure")); firstHeader = false; continue; } res.addHeader(HttpHeaders.SET_COOKIE, String.format("%s; %s", header, "SameSite=None")); LOG.info(String.format("Same Site Filter Remaining Headers %s; %s", header, "SameSite=None; Secure")); } chain.doFilter(req, res); } @Override public void destroy() { LOG.warn("Same Site Filter Destructing filter :{}", this); } }
This allows for addition of the required headers in the response containing the cookie