> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# CSRF protection

> Understand how CSRF attacks work and how Laravel 13 defends against them with Origin verification and token verification.

## Introduction

CSRF (Cross-Site Request Forgery) is an attack that tricks an authenticated user into making unintended requests by impersonating them.

For example, suppose your application has a `POST /user/email` route that accepts an email address change. If an attacker embeds a form on another site that automatically submits to this URL, the user's email address could be changed without them noticing.

In Laravel 13, CSRF protection is enabled by default via a mechanism included in the `web` middleware group.

## Preventing CSRF attacks

Laravel's `PreventRequestForgery` middleware protects against CSRF using two layers:

1. **Origin verification** (the `Sec-Fetch-Site` header)
2. **Token verification** (per-session CSRF token)

It first checks the Origin, and falls back to token verification if it can't determine the result or verification fails.

## Origin verification

Laravel first checks the `Sec-Fetch-Site` header to determine whether the request is from the same origin. This is especially effective in HTTPS environments.

If Origin verification passes, the request is allowed at that point. If not, CSRF token verification is performed as before.

<Warning>
  `Sec-Fetch-Site` is designed to be used with HTTPS connections. In HTTP environments, Origin verification does not work, and token verification serves as the primary defense.
</Warning>

### Origin-only mode

You can also disable the fallback to token verification and make the decision purely based on Origin verification.

```php theme={null}
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Middleware;

return Application::configure(basePath: dirname(__DIR__))
    ->withMiddleware(function (Middleware $middleware): void {
        $middleware->preventRequestForgery(originOnly: true);
    });
```

In Origin-only mode, requests that fail Origin verification return `403` instead of `419`.

If you want to allow same-site requests (such as between subdomains), set `allowSameSite`.

```php theme={null}
$middleware->preventRequestForgery(allowSameSite: true);
```

## Token verification

Laravel generates a CSRF token per session. You can retrieve it via `csrf_token()` or from the session.

```php theme={null}
use Illuminate\Http\Request;

Route::get('/token', function (Request $request) {
    $tokenFromSession = $request->session()->token();
    $tokenFromHelper = csrf_token();
});
```

When creating `POST`, `PUT`, `PATCH`, or `DELETE` forms in `web` routes, always include `@csrf`.

```blade theme={null}
<form method="POST" action="/profile">
    @csrf

    <!-- Equivalent hidden input -->
    <input type="hidden" name="_token" value="{{ csrf_token() }}" />
</form>
```

## Excluding URIs

For requests sent from external services like Stripe webhooks, you may want to exclude certain URIs from CSRF protection.

```php theme={null}
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Middleware;

return Application::configure(basePath: dirname(__DIR__))
    ->withMiddleware(function (Middleware $middleware): void {
        $middleware->preventRequestForgery(except: [
            'stripe/*',
            'http://example.com/foo/bar',
            'http://example.com/foo/*',
        ]);
    });
```

<Info>
  Where possible, place webhook routes outside the `web` middleware group and keep exclusion settings to a minimum.
</Info>

## X-CSRF-TOKEN header

In addition to the `_token` form field, Laravel also verifies the `X-CSRF-TOKEN` header.

First, output the token in a meta tag.

```blade theme={null}
<meta name="csrf-token" content="{{ csrf_token() }}">
```

Then attach the value to your AJAX request header.

```js theme={null}
$.ajaxSetup({
    headers: {
        'X-CSRF-TOKEN': document
            .querySelector('meta[name="csrf-token"]')
            .getAttribute('content'),
    },
});
```

## X-XSRF-TOKEN header

Laravel also sends an encrypted `XSRF-TOKEN` cookie. Axios and Angular can automatically set this value in the `X-XSRF-TOKEN` header on same-origin requests.

For that reason, CSRF protection may work in SPA or AJAX implementations without manually setting the header.

## SPA considerations

When using Laravel as an API backend for an SPA, first obtain the CSRF cookie, then send the login request.

```js theme={null}
await axios.get('/sanctum/csrf-cookie');
await axios.post('/login', {
    email: 'user@example.com',
    password: 'password',
});
```

See [Sanctum](/en/sanctum) for details.


## Related topics

- [Laravel Fetch Metadata](/en/packages/laravel-fetch-metadata.md)
- [March 2026 Laravel updates](/en/blog/changelog/202603.md)
- [Blade templates](/en/blade.md)
- [Middleware](/en/middleware.md)
- [Laravel Sanctum (API Token Authentication)](/en/sanctum.md)
