Preventing Cross-Site Request Forgery (CSRF) attacks

Loading

Cross-Site Request Forgery (CSRF) is a security vulnerability where an attacker tricks a user into executing unwanted actions on a web application in which they are authenticated. CSRF attacks can manipulate user data, perform transactions, or change account settings without the user’s consent.

AngularJS has built-in CSRF protection mechanisms, but developers must also implement backend security measures to fully protect applications.


1. How CSRF Attacks Work

CSRF exploits the fact that browsers automatically send cookies with every request to a domain where the user is logged in.

Example CSRF Attack

  1. A user logs into example.com and remains authenticated.
  2. The attacker tricks the user into clicking a malicious link or loading an image on another website: <img src="https://example.com/api/transfer?amount=5000&to=attacker_account">
  3. The browser sends the session cookies along with the request.
  4. Since the user is authenticated, the request is executed successfully without their knowledge.

2. AngularJS’s Built-in CSRF Protection

AngularJS provides CSRF protection by default using CSRF tokens.

How AngularJS Handles CSRF

  • AngularJS expects the server to send a CSRF token in a cookie (XSRF-TOKEN).
  • For every request, AngularJS automatically includes the token as a custom header (X-XSRF-TOKEN).
  • The server verifies that the token matches before processing the request.

3. Implementing CSRF Protection in AngularJS

A. Setting Up CSRF Tokens in the Backend

The backend must send a CSRF token as a cookie.

Example: Setting CSRF Token in Express (Node.js)

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

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

app.use((req, res, next) => {
res.cookie('XSRF-TOKEN', req.csrfToken()); // Set CSRF token in cookie
next();
});

Example: Setting CSRF Token in Django

from django.middleware.csrf import get_token
def set_csrf_token(request):
response = HttpResponse()
response.set_cookie('XSRF-TOKEN', get_token(request))
return response

Example: Setting CSRF Token in Laravel (PHP)

setcookie('XSRF-TOKEN', csrf_token(), time()+3600, "/");

B. AngularJS Automatically Sends the Token

AngularJS automatically reads the XSRF-TOKEN cookie and includes it in every HTTP request.

No Extra Code Required in AngularJS

$http.post('/api/update', { data: "secureData" })
.then(response => console.log("Success"),
error => console.error("CSRF Token Invalid"));

AngularJS sends:

X-XSRF-TOKEN: {csrf_token_value}

The server validates the token before processing the request.


C. Manually Adding CSRF Token in HTTP Headers

If needed, you can manually add the CSRF token to headers.

Example: Adding CSRF Token Manually in AngularJS

app.config(function($httpProvider) {
$httpProvider.defaults.headers.common['X-XSRF-TOKEN'] = getCookie('XSRF-TOKEN');
});

function getCookie(name) {
var value = "; " + document.cookie;
var parts = value.split("; " + name + "=");
if (parts.length === 2) return parts.pop().split(";").shift();
}

4. Implementing Additional CSRF Protections

A. Use SameSite Attribute in Cookies

Setting SameSite=Strict prevents cookies from being sent with cross-site requests.

Example: Set SameSite Attribute in Express (Node.js)

app.use((req, res, next) => {
res.cookie('XSRF-TOKEN', req.csrfToken(), { httpOnly: false, sameSite: 'Strict' });
next();
});

Example: Set SameSite Attribute in PHP

setcookie("XSRF-TOKEN", $csrf_token, time()+3600, "/", "", false, true);

B. Verify HTTP Referer and Origin Headers

The backend should reject requests from unknown origins.

Example: Check Origin in Node.js

app.use((req, res, next) => {
const allowedOrigin = "https://example.com";
if (req.headers.origin !== allowedOrigin) {
return res.status(403).send("Forbidden");
}
next();
});

Example: Check Referer in Django

from django.middleware.csrf import REASON_NO_REFERER
if request.META.get('HTTP_REFERER') != 'https://example.com/':
raise PermissionDenied(REASON_NO_REFERER)

C. Require CSRF Tokens Only for State-Changing Requests

CSRF tokens should be validated only for POST, PUT, DELETE, PATCH requests, not GET requests.

Example: Allowing Safe HTTP Methods

app.use((req, res, next) => {
if (["POST", "PUT", "DELETE", "PATCH"].includes(req.method)) {
if (!req.cookies["XSRF-TOKEN"]) return res.status(403).send("CSRF Token Missing");
}
next();
});

D. Implement a “Double Submit Cookie” Defense

If the backend doesn’t store sessions, use the Double Submit Cookie method.

How It Works

  1. The server sends the XSRF-TOKEN cookie.
  2. AngularJS sends the cookie and includes it in a custom header.
  3. The server verifies that both values match.

Example: Backend Verifying the Double Submit Token (Node.js)

app.use((req, res, next) => {
const csrfCookie = req.cookies['XSRF-TOKEN'];
const csrfHeader = req.headers['x-xsrf-token'];

if (!csrfCookie || csrfCookie !== csrfHeader) {
return res.status(403).send("CSRF Token Mismatch");
}
next();
});

Leave a Reply

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