Implementing CSRF protection in AngularJS

Loading

Cross-Site Request Forgery (CSRF) is a security vulnerability where an attacker tricks a user into making unintended requests to a web application where they are authenticated. This can lead to unauthorized actions being performed on behalf of the user.

AngularJS has built-in support for CSRF protection, but proper server-side handling is also necessary. In this guide, we will cover:

  1. Understanding CSRF Attacks
  2. How CSRF Protection Works in AngularJS
  3. Configuring CSRF Protection in AngularJS (XSRF-TOKEN)
  4. Implementing CSRF Protection on the Server
  5. Customizing CSRF Token Handling in AngularJS
  6. Additional CSRF Prevention Measures
  7. Testing CSRF Protection
  8. Best Practices for CSRF Security

1. Understanding CSRF Attacks

A CSRF attack happens when:

  1. A victim logs into a web application (e.g., bank.com).
  2. The session is authenticated using cookies.
  3. The victim visits a malicious website while still logged in.
  4. The malicious website sends a forged request (e.g., money transfer) using the victim’s session cookies.
  5. The request is executed because the server trusts the user’s session.

Example of a CSRF Attack

<img src="https://bank.com/api/transfer?amount=1000&to=attacker" />

If the user is logged into bank.com, the request will be executed without their consent.


2. How CSRF Protection Works in AngularJS

AngularJS mitigates CSRF attacks using anti-CSRF tokens. The mechanism works as follows:

  • The server sets a CSRF token in a cookie (XSRF-TOKEN).
  • The AngularJS app reads the token from the cookie and adds it to each HTTP request as the X-XSRF-TOKEN header.
  • The server verifies the token before processing the request.

3. Configuring CSRF Protection in AngularJS

AngularJS automatically sends the CSRF token with every $http request.

Step 1: Enabling CSRF Support in AngularJS

Ensure your application uses $http for API requests:

var app = angular.module('myApp', []);

app.config(function($httpProvider) {
// Enable CSRF protection
$httpProvider.defaults.xsrfCookieName = 'XSRF-TOKEN';
$httpProvider.defaults.xsrfHeaderName = 'X-XSRF-TOKEN';
});

Step 2: Sending API Requests with CSRF Token

Once configured, AngularJS automatically includes the CSRF token in each request:

app.controller('MainController', function($scope, $http) {
$http.post('/api/update-profile', { name: 'John Doe' })
.then(response => {
console.log('Profile updated:', response.data);
})
.catch(error => {
console.error('Error:', error);
});
});

This request will include the X-XSRF-TOKEN header.


4. Implementing CSRF Protection on the Server

The server must:

  1. Set a CSRF token cookie on login or page load.
  2. Validate the token in incoming requests.

CSRF Protection in Different Backend Frameworks

Node.js (Express.js)

Install the csurf package:

npm install csurf cookie-parser

Set up CSRF protection:

const express = require('express');
const csrf = require('csurf');
const cookieParser = require('cookie-parser');

const app = express();
app.use(cookieParser());
app.use(csrf({ cookie: true }));

// Send CSRF token to frontend
app.get('/csrf-token', (req, res) => {
res.json({ csrfToken: req.csrfToken() });
});

// Example protected API route
app.post('/api/update-profile', (req, res) => {
res.json({ message: 'Profile updated successfully' });
});

app.use((err, req, res, next) => {
if (err.code === 'EBADCSRFTOKEN') {
res.status(403).json({ error: 'Invalid CSRF token' });
} else {
next(err);
}
});

app.listen(3000, () => console.log('Server running on port 3000'));

Django

Enable CSRF protection in settings.py:

MIDDLEWARE = [
'django.middleware.csrf.CsrfViewMiddleware',
]

Modify views to return CSRF token:

from django.middleware.csrf import get_token
from django.http import JsonResponse

def csrf_token(request):
return JsonResponse({'csrfToken': get_token(request)})

Spring Boot (Java)

Enable CSRF protection in SecurityConfig.java:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
}
}

5. Customizing CSRF Token Handling in AngularJS

If the backend uses a custom CSRF mechanism, update AngularJS to match it.

Custom CSRF Token Cookie Name

$httpProvider.defaults.xsrfCookieName = 'CUSTOM-CSRF-TOKEN';
$httpProvider.defaults.xsrfHeaderName = 'X-CUSTOM-CSRF-TOKEN';

Manually Fetching the CSRF Token

app.run(function($http) {
$http.get('/csrf-token').then(response => {
document.cookie = `XSRF-TOKEN=${response.data.csrfToken}`;
});
});

6. Additional CSRF Prevention Measures

Besides CSRF tokens, implement:

SameSite Cookies – Prevent cookies from being sent in cross-origin requests.

app.use(cookieParser({ sameSite: 'Strict' }));

Referer & Origin Validation – Verify Referer and Origin headers.

User Authentication Checks – Ensure requests are properly authenticated.

Use POST Instead of GET – Prevent sensitive actions via GET requests.


7. Testing CSRF Protection

Test Cases

  1. Valid CSRF Token – API should process the request.
  2. Missing CSRF Token – API should reject the request.
  3. Invalid CSRF Token – API should return a 403 Forbidden error.

Testing Using Postman

  • Send a POST request without X-XSRF-TOKEN. It should be blocked.
  • Send a POST request with X-XSRF-TOKEN. It should be allowed.

Testing with an Attack Script

<form action="https://example.com/api/update-profile" method="POST">
<input type="hidden" name="name" value="Attacker" />
<input type="submit" value="Submit Attack" />
</form>

If CSRF protection is working, the request should be blocked.

Leave a Reply

Your email address will not be published. Required fields are marked *