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
