SPEAK

Protecting against cross-site request forgery

Abstract

This topic describes how to use Angular's features to protect against cross-site request forgery (CSRF or XSRF) attacks.

The Angular security documentation describes how Angular protects against cross-site request forgery (CSRF, or sometimes XSRF) attempts:

A common technique is that the application server sends a randomly generated authentication token in a cookie. The client code then reads this cookie and adds a custom request header with the token in all subsequent requests. The server compares the received cookie value to the request header value and rejects the request if the values are missing or they do not match.

In SPEAK 3, when a user requests a page, the SPEAK 3 entry point sets two anti-CSRF cookies. The client must pass the token to the server using one of the following options:

The server code verifies that the original key stored in cookies and the token that the client passes correspond, either as the header or as the request body.

We recommend this option. This is by far the easiest approach, since it uses the built-in security functionality shipped as part of Angular.

You can apply this option for Web API services that use the [ValidateHttpAntiForgeryToken] attribute and the X-RequestVerificationToken header.

However, Angular sets a header with the name X-XSRF-TOKEN.

You can change the header name to match the one expected by the backend service:

  • Use the SPEAK 3 entry-point solution

  • Import the SciAntiCSRFModule from @speak/ng-sc into your app.module.ts file:

    import { SciAntiCSRFModule } from '@speak/ng-sc/anti-csrf';
    @NgModule({
      imports: [
        SciAntiCSRFModule,
        ...
      ],
      ...
    })
    

This implements Anti-CSRF support, as long as the application uses the Angular HTTP module to make requests.

Use this option for ASP.NET MVC or ASP.NET Web Forms services.

If the service you want to access uses the [ValidateAntiForgeryToken] attribute, you cannot use the send as a request header option. Instead, your application must pass the XSRF-TOKEN token in the __RequestVerificationToken request body key for each HTTP request it makes.

This code snippet illustrates how to use this option:

import { Http, Response, Headers, RequestOptions } from '@angular/http';
import { parseCookieValue } from '@speak/ng-sc/core';
@Injectable()
export class MyService {
  cookieName: string = 'XSRF-TOKEN';
  tokenKey: string = '__RequestVerificationToken';
  serviceUrl = '/path/to/my/service';
  myMethod() {
    const xsrfToken = parseCookieValue(document.cookie, this.cookieName);
    const body = new URLSearchParams();
    body.append(this.tokenKey, xsrfToken);
    const headers = new Headers({'Content-Type': 'application/x-www-form-urlencoded'});
    const options = new RequestOptions({ headers });
    this.http.post(this.serviceUrl, body.toString(), options)
      .subscribe(() => {
        // do your thing
      });
  }
}

Your application must include this code with every request.

Note

For more information, the OWASP site describes Cross-Site Request Forgery (CSRF).

The Angular site describes HTTP-level vulnerabilities.