14

I am trying to learn Spring Security right now and I have seen many different examples using this. I know what CSRF is and that Spring Security enables it by default. The thing that I am curious about to know is this kind of customization.

  .csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
  .and()
  .authorizeRequests(request -> {
                request
                    .antMatchers("/login").permitAll()
                    .anyRequest()
                    ....more code

What kind of customization does .csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) this line and when it is appropriate to use it. I would appreciate it if anyone can come with a simple explanation.

Romil Patel
  • 12,879
  • 7
  • 47
  • 76
Fazli Zekiqi
  • 531
  • 2
  • 7
  • 14

2 Answers2

26

CSRF stands for Cross Site Request Forgery

It is one kind of token that is sent with the request to prevent the attacks. In order to use the Spring Security CSRF protection, we'll first need to make sure we use the proper HTTP methods for anything that modifies the state (PATCH, POST, PUT, and DELETE – not GET).

CSRF protection with Spring CookieCsrfTokenRepository works as follows:

  • The client makes a GET request to Server (Spring Boot Backend), e.g. request for the main page
  • Spring sends the response for GET request along with Set-cookie header which contains securely generated XSRF Token
  • The browser sets the cookie with XSRF Token
  • While sending a state-changing request (e.g. POST) the client (might be angular) copies the cookie value to the HTTP request header
  • The request is sent with both header and cookie (browser attaches the cookie automatically)
  • Spring compares the header and the cookie values, if they are the same the request is accepted, otherwise, 403 is returned to the client

The method withHttpOnlyFalse allows angular to read XSRF cookie. Make sure that Angular makes XHR request with withCreddentials flag set to true.


Code from CookieCsrfTokenRepository

@Override
public CsrfToken generateToken(HttpServletRequest request) {
    return new DefaultCsrfToken(this.headerName, this.parameterName,
            createNewToken());
}

@Override
public void saveToken(CsrfToken token, HttpServletRequest request,
        HttpServletResponse response) {
    String tokenValue = token == null ? "" : token.getToken();
    Cookie cookie = new Cookie(this.cookieName, tokenValue);
    cookie.setSecure(request.isSecure());
    if (this.cookiePath != null && !this.cookiePath.isEmpty()) {
            cookie.setPath(this.cookiePath);
    } else {
            cookie.setPath(this.getRequestContext(request));
    }
    if (token == null) {
        cookie.setMaxAge(0);
    }
    else {
        cookie.setMaxAge(-1);
    }
    cookie.setHttpOnly(cookieHttpOnly);
    if (this.cookieDomain != null && !this.cookieDomain.isEmpty()) {
        cookie.setDomain(this.cookieDomain);
    }

    response.addCookie(cookie);
}

@Override
public CsrfToken loadToken(HttpServletRequest request) {
    Cookie cookie = WebUtils.getCookie(request, this.cookieName);
    if (cookie == null) {
        return null;
    }
    String token = cookie.getValue();
    if (!StringUtils.hasLength(token)) {
        return null;
    }
    return new DefaultCsrfToken(this.headerName, this.parameterName, token);
}


public static CookieCsrfTokenRepository withHttpOnlyFalse() {
    CookieCsrfTokenRepository result = new CookieCsrfTokenRepository();
    result.setCookieHttpOnly(false);
    return result;
}

You may explore the methods here

Romil Patel
  • 12,879
  • 7
  • 47
  • 76
  • 1
    Does 'withHttpOnlyFalse' only applies for angular or does it also apply for react and other js frameworks? – Fazli Zekiqi Jun 30 '20 at 08:31
  • 3
    It should apply to all the client frameworks angular, react etc – Romil Patel Jun 30 '20 at 08:40
  • 3
    The answer has much to say about CSRF but it does little to answer TO's initial question. – simou Oct 26 '21 at 23:08
  • @FazliZekiqi I think it applies to any front-end framework as by using `.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())` you get a CSRF token cookie response even with Postman. – Valentin Popescu Apr 14 '22 at 11:00
  • 2
    `withHttpOnlyFalse` makes browser have the ability to read cookies by javascript code. What if a hacker injects some code and reads the XSRF Token of the cookie, and then sends forged http request with that XSRF Token and the cookie itself? Back-end may think the forged request is illegal. – Name Null Oct 29 '22 at 12:18
  • @NameNull I believe that if application is protected against XSS, hacker might not be able to easily inject code. I more of worry if user access evil.com website, and the evil website has script to read from the cookie, the website can send a request to the victim website with CSRF attack. Cos the evil website can set the csrf header and attached cookie in the reequest to be the same value – Nick Wills Jan 01 '23 at 11:22
0

You may find additional information about the httpOnly attribute of cookies here: https://www.cookiepro.com/knowledge/httponly-cookie/

Laurent Picquet
  • 1,147
  • 11
  • 12