GitHub

Expired CSRF tokens

A token expires with the session. The browser gets a new one and sends the request again, so the user does not lose what they did.
  • Answer the rejected request

    The response carries the new token. The browser applies it and sends the request again, once.

  • Or name a refresh URL

    On a 419 the browser requests the URL, which answers with a new token, and then repeats the request.

  • Laravel 13

    A same-origin request of a modern browser passes on its origin alone. This demo checks the token too, to show the recovery.

Controller.php
// bootstrap/app.php
$exceptions->render(function (HttpException $e, Request $request) {
    // Laravel turns a TokenMismatchException into a 419
    if ($e->getStatusCode() === 419 && $request->ajax()) {
        return (new AsyncResponse())
            ->retryWithCSRFToken(csrf_token())
            ->send();
    }
});

// where the token is set, e.g. in a middleware
BigPipe::setCSRFToken(
    csrf_token(),
    refreshUri: route('csrf-token', absolute: false)
);
Try it
  1. Replace the token of the session, as if it had expired.

    Expire the token
  2. Save. The request still carries the old token.

    Save

An expired token

Watch the responses: the save is rejected with a new token, sent again, and the user only sees the result.