Maltram
Maltram

Reputation: 49

CSRF with Spring and Angular 2

I am trying to implent CSRF-protection with Spring Security (4.1.3) and Angular 2.0.1

There are many sources to related topics but I cannot find a clear instruction. Some of the statements even contradict each other.

I read about springs way of doing it (though the guide describes the Angular 1 way) Spring Security Guide with Angular IT implies, that with .csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());

everything should work "out of the box". Even further the angular guide to security describes the CSRF-protection as build in.

In my enviroment the POST looks like this:

Why doesn't Angular send the header, too? How is this secure if Spring only checks the provided cookie and the provided header with no serverside action whatsoever?

There are some similar questions like this but the only answer with 0 upvotes seems (to me) plain wrong, as CSRF, from my understanding, has to have a serverside check for the cookie validation.

This question only provides information on how to change the cookie or header name as explained here

What am I missing here? I doubt there is a mistake in the Spring Security implementation but I cannot quite get it to work.

Any ideas?

POST-call

login(account: Account): Promise<Account> {  


   let headers = new Headers({ 'Content-Type': 'application/json' });
    headers.append('X-TENANT-ID', '1');
    headers.append('Authorization', 'Basic ' + btoa(account.userName + ':' + account.password));
    let options = new RequestOptions({ headers: headers, withCredentials:true });
   return this.http.post(this.loginUrl, account, options).toPromise()
  .then(this.extractData)
  .catch(this.handleError)

}

Spring Security Config

 [] csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())

OPTIONS header

POST header

Upvotes: 1

Views: 3095

Answers (1)

Maltram
Maltram

Reputation: 49

The problem was the application path. Spring has the option to set the cookie-path in its pipeline but it is not released yet.

I had to write my own implementation for the CsrfTokenRepository which would accept a different cookie path.

Those are the relevant bits:

public final class CookieCsrfTokenRepository implements CsrfTokenRepository

private String cookiePath;

 @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());
    // cookie.setPath(getCookiePath(request));
    if (this.cookiePath != null && !this.cookiePath.isEmpty()) {
        cookie.setPath(this.cookiePath);
    } else {
        cookie.setPath(getRequestContext(request));
    }

    if (token == null) {
        cookie.setMaxAge(0);
    } else {
        cookie.setMaxAge(-1);
    }
    if (cookieHttpOnly && setHttpOnlyMethod != null) {
        ReflectionUtils.invokeMethod(setHttpOnlyMethod, cookie, Boolean.TRUE);
    }

    response.addCookie(cookie);
}

public void setCookiePath(String path) {
    this.cookiePath = path;
}

public String getCookiePath() {
    return this.cookiePath;
}

Upvotes: 1

Related Questions