# Protect forms and requests with CSRF tokens

> Create a token with $.csrf(), send it with the request and verify it in a middleware so cross-site requests are rejected.

Framework: total5
Product: Total.js 5 (total5@0.0.19)
Language: en
Content-SHA256: e10434ff98f2737ef66f4645652b5c226dd2bc4b75b4c4a3bc5d348b2d366762
Snapshot: c0700e321579725c5cf4f5ace1ad7d2866d1b4f93c24a63c0b41b6b7998e976c
Sources: total5-installed@total5@0.0.19
Review: not-recorded

A CSRF attack makes a logged-in user's browser send a request they never intended. The defence is a token that the page receives from your server and that has to come back with every state-changing request. Total.js creates and verifies the token for you, but only when `secret_csrf` is set in the `config` file (without it the check always passes).

`$.csrf()` returns a token (and `@{csrf}` prints it in a view). It is an encrypted value tied to the **IP address** and the **user agent** of the client and it expires after the time in `$csrfexpiration` (30 minutes by default). `DEF.onCSRFcheck($)` verifies the token that came back, read from the `x-csrf-token` header or the `csrf` query string parameter, and returns `true` or `false`. For ordinary routes you call it yourself, most conveniently from a middleware that you add with `#csrf` to every route that changes data. WebSocket routes with the `@csrf` flag are checked automatically.

```text config
secret_csrf : change-this-secret-in-production
```

```js definitions/csrf.js
MIDDLEWARE('csrf', function($, next) {
	if (DEF.onCSRFcheck($))
		next();
	else
		$.invalid(403);
});
```

```js controllers/csrf.js
exports.install = function() {
	ROUTE('GET /form/', form);
	ROUTE('POST /transfer/ @json #csrf', transfer);
};

function form($) {
	$.json({ csrf: $.csrf() });
}

function transfer($) {
	$.json({ ok: true, amount: $.body.amount });
}
```
