PHPackages                             yiisoft/csrf - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Framework](/categories/framework)
4. /
5. yiisoft/csrf

ActiveLibrary[Framework](/categories/framework)

yiisoft/csrf
============

Yii CSRF Protection Library

2.2.3(6mo ago)27284.3k—3.1%9[4 issues](https://github.com/yiisoft/csrf/issues)[1 PRs](https://github.com/yiisoft/csrf/pulls)8BSD-3-ClausePHPPHP ~7.4.0 || 8.0 - 8.5CI passing

Since Feb 23Pushed 2w ago13 watchersCompare

[ Source](https://github.com/yiisoft/csrf)[ Packagist](https://packagist.org/packages/yiisoft/csrf)[ Docs](https://www.yiiframework.com/)[ GitHub Sponsors](https://github.com/sponsors/yiisoft)[ OpenCollective](https://opencollective.com/yiisoft)[ RSS](/packages/yiisoft-csrf/feed)WikiDiscussions master Synced 2d ago

READMEChangelog (7)Dependencies (18)Versions (18)Used By (8)

 [ ![Yii](https://camo.githubusercontent.com/8317c17418b39410a660f5149071d26c5023c0d5fb2b7ebb771324812f666d73/68747470733a2f2f796969736f66742e6769746875622e696f2f646f63732f696d616765732f7969695f6c6f676f2e737667) ](https://github.com/yiisoft)

Yii CSRF Protection Library
===========================

[](#yii-csrf-protection-library)

[![Latest Stable Version](https://camo.githubusercontent.com/0b51396c51069ce2b3cf1eacc0c0c6c57f42c7ee4b9ac2dd431df60845d74c06/68747470733a2f2f706f7365722e707567782e6f72672f796969736f66742f637372662f76)](https://packagist.org/packages/yiisoft/csrf)[![Total Downloads](https://camo.githubusercontent.com/1092eea73e9fd989570f30f8acbd7f0b0c5c22485c6e1d0542655074eef8a3b4/68747470733a2f2f706f7365722e707567782e6f72672f796969736f66742f637372662f646f776e6c6f616473)](https://packagist.org/packages/yiisoft/csrf)[![Build status](https://github.com/yiisoft/csrf/actions/workflows/build.yml/badge.svg)](https://github.com/yiisoft/csrf/actions/workflows/build.yml)[![Code coverage](https://camo.githubusercontent.com/18d423c6822f824654c1ad8813b1e9ab7799a87463c93f13dc0b0239fcb76e9c/68747470733a2f2f636f6465636f762e696f2f67682f796969736f66742f637372662f67726170682f62616467652e7376673f746f6b656e3d415056374e4d49414231)](https://codecov.io/gh/yiisoft/csrf)[![Mutation testing badge](https://camo.githubusercontent.com/72c9b285989f3cb867f85479267d4e5ee614020074b9d1d7ed3ac1a1acde120e/68747470733a2f2f696d672e736869656c64732e696f2f656e64706f696e743f7374796c653d666c61742675726c3d687474707325334125324625324662616467652d6170692e737472796b65722d6d757461746f722e696f2532466769746875622e636f6d253246796969736f6674253246637372662532466d6173746572)](https://dashboard.stryker-mutator.io/reports/github.com/yiisoft/csrf/master)[![static analysis](https://github.com/yiisoft/csrf/workflows/static%20analysis/badge.svg)](https://github.com/yiisoft/csrf/actions?query=workflow%3A%22static+analysis%22)[![type-coverage](https://camo.githubusercontent.com/f469754419869f71851d1ad474b499da8dbb5dfabb31f51fbb08ffb37b07f2b9/68747470733a2f2f73686570686572642e6465762f6769746875622f796969736f66742f637372662f636f7665726167652e737667)](https://shepherd.dev/github/yiisoft/csrf)

The package provides [PSR-15](https://www.php-fig.org/psr/psr-15/) middleware for CSRF protection:

- It supports two algorithms out of the box:
    - Synchronizer CSRF token with customizable token generation and storage. By default, it uses random data and session.
    - HMAC based token with customizable identity generation. Uses session by default.
- It has ability to apply masking to CSRF token string to make [BREACH attack](https://breachattack.com/) impossible.
- It supports CSRF protection by custom header for AJAX/SPA backend API.

Requirements
------------

[](#requirements)

- PHP 7.4 - 8.5.

Installation
------------

[](#installation)

The package could be installed with [Composer](https://getcomposer.org):

```
composer require yiisoft/csrf
```

General usage
-------------

[](#general-usage)

In order to enable CSRF protection you need to add `CsrfTokenMiddleware` to your main middleware stack. In Yii it is done by configuring [`MiddlewareDispatcher`](https://github.com/yiisoft/middleware-dispatcher):

```
$middlewareDispatcher = $injector->make(MiddlewareDispatcher::class);
$middlewareDispatcher = $middlewareDispatcher->withMiddlewares([
    ErrorCatcher::class,
    SessionMiddleware::class,
    CsrfTokenMiddleware::class, //  [
        'withMiddlewares()' => [[
            ErrorCatcher::class,
            SessionMiddleware::class,
            CsrfTokenMiddleware::class, // getValue();
```

If the token does not pass validation, the response `422 Unprocessable Entity` will be returned. You can change this behavior by implementing your own request handler:

```
use Psr\Http\Message\ResponseFactoryInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Yiisoft\Csrf\CsrfTokenMiddleware;

/**
 * @var Psr\Http\Message\ResponseFactoryInterface $responseFactory
 * @var Yiisoft\Csrf\CsrfTokenInterface $csrfToken
 */

$failureHandler = new class ($responseFactory) implements RequestHandlerInterface {
    private ResponseFactoryInterface $responseFactory;

    public function __construct(ResponseFactoryInterface $responseFactory)
    {
        $this->responseFactory = $responseFactory;
    }

    public function handle(ServerRequestInterface $request): ResponseInterface
    {
        $response = $this->responseFactory->createResponse(400);
        $response
            ->getBody()
            ->write('Bad request.');
        return $response;
    }
};

$middleware = new CsrfTokenMiddleware($responseFactory, $csrfToken, $failureHandler);
```

By default, `CsrfTokenMiddleware` considers `GET`, `HEAD`, `OPTIONS` methods as safe operations and doesn't perform CSRF validation. You can change this behavior as follows:

```
use Yiisoft\Csrf\CsrfTokenMiddleware;
use Yiisoft\Http\Method;

$csrfTokenMiddleware = $container->get(CsrfTokenMiddleware::class);

// Returns a new instance with the specified list of safe methods.
$csrfTokenMiddleware = $csrfTokenMiddleware->withSafeMethods([Method::OPTIONS]);

// Returns a new instance with the specified header name.
$csrfTokenMiddleware = $csrfTokenMiddleware->withHeaderName('X-CSRF-PROTECTION');
```

or define the `CsrfTokenMiddleware` configuration in the [DI container](https://github.com/yiisoft/di):

```
// config/web/di/csrf-token.php
use Yiisoft\Csrf\CsrfTokenMiddleware;
use Yiisoft\Http\Method;

return [
    CsrfTokenMiddleware::class => [
        'withSafeMethods()' => [[Method::OPTIONS]],
        'withHeaderName()' => ['X-CSRF-PROTECTION'],
    ],
];
```

CSRF Tokens
-----------

[](#csrf-tokens)

In case Yii framework is used along with config plugin, the package is [configured](./config/di-web.php)automatically to use synchronizer token and masked decorator. You can change that depending on your needs.

Use synchronizer token for sensitive anonymous forms; use HMAC token for authenticated-only forms when a submitted token may stay valid for a few minutes.

 ```
flowchart TD
    A{Anonymous forms to protect?}
    A -- Yes --> S[Synchronizer]
    A -- No --> B{Old or repeated submits must fail?}
    B -- Yes --> S
    B -- No --> C{Per-environment secret key?}
    C -- No --> S
    C -- Yes --> D{Token replay within lifetime OK?}
    D -- No --> S
    D -- Yes --> H[HMAC]
```

      Loading Detailed comparison:

FactorSynchronizerHMACI/O per requestSession read and writeNo token storage I/OFile based session GCMay scan session filesNot triggered by CSRF token storageToken storage growthDepends on session storageNothing to storeToken revocationPossible by removing stored tokenNot possible before token expirationReplay within lifetimePrevented by storage policyPossible until the token expiresTo switch token to HMAC:

```
use Yiisoft\Csrf\CsrfTokenInterface;
use Yiisoft\Csrf\Hmac\HmacCsrfToken;
use Yiisoft\Csrf\MaskedCsrfToken;
use Yiisoft\Definitions\Reference;

return [
    CsrfTokenInterface::class => [
        'class' => MaskedCsrfToken::class,
        '__construct()' => [
            'token' => Reference::to(HmacCsrfToken::class),
        ],
    ],
];
```

### Synchronizer CSRF token

[](#synchronizer-csrf-token)

Synchronizer CSRF token is a stateful CSRF token that is a unique random string. It is saved in persistent storage available only to the currently logged-in user. The same token is added to a form. When the form is submitted, token that came from the form is compared against the token stored.

`SynchronizerCsrfToken` requires implementation of the following interfaces:

- `CsrfTokenGeneratorInterface` for generating a new CSRF token;
- `CsrfTokenStorageInterface` for persisting a token between requests.

Package provides `RandomCsrfTokenGenerator` that generates a random token and `SessionCsrfTokenStorage` that persists a token between requests in a user session.

To learn more about the synchronizer token pattern, [check OWASP CSRF cheat sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html#synchronizer-token-pattern).

### HMAC based token

[](#hmac-based-token)

HMAC based token is a stateless CSRF token that does not require any storage. The token is a hash from session ID and a timestamp used to prevent replay attacks. The token is added to a form. When the form is submitted, we re-generate the token from the current session ID and a timestamp from the original token. If two hashes match, we check that the timestamp is less than the token lifetime.

`HmacCsrfToken` requires implementation of `CsrfTokenIdentityGeneratorInterface` for generating an identity. The package provides `SessionCsrfTokenIdentityGenerator` that is using session ID thus making the session a token scope.

Parameters set via the `HmacCsrfToken` constructor are:

- `$secretKey` — shared secret key used to generate the hash;
- `$algorithm` — hash algorithm for message authentication. `sha256`, `sha384` or `sha512` are recommended;
- `$lifetime` — number of seconds that the token is valid for.

When using HMAC with the config plugin, configure these constructor arguments through parameters:

```
return [
    'yiisoft/csrf' => [
        'hmacToken' => [
            'secretKey' => (string) getenv('YII_CSRF_SECRET_KEY'),
            'algorithm' => 'sha256',
            'lifetime' => 300,
        ],
    ],
];
```

To learn more about HMAC based token pattern [check OWASP CSRF cheat sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html#hmac-based-token-pattern).

### Stub CSRF token

[](#stub-csrf-token)

The `StubCsrfToken` simply stores and returns a token string. It does not perform any additional validation. This implementation can be useful when mocking CSRF token behavior during unit testing or when providing placeholder functionality in temporary solutions.

### Masked CSRF token

[](#masked-csrf-token)

`MaskedCsrfToken` is a decorator for `CsrfTokenInterface` that applies masking to a token string. It makes [BREACH attack](https://breachattack.com/) impossible, so it is safe to use token in HTML to be later passed to the next request either as a hidden form field or via JavaScript async request.

It is recommended to always use this decorator.

CSRF protection for AJAX/SPA backend API
----------------------------------------

[](#csrf-protection-for-ajaxspa-backend-api)

If you are using a cookie to authenticate your AJAX/SPA, then you do need CSRF protection for the backend API.

### Employing custom request header

[](#employing-custom-request-header)

In this pattern, AJAX/SPA frontend appends a custom header to API requests that require CSRF protection. No token is needed for this approach. This defense relies on the CORS preflight mechanism which sends an `OPTIONS` request to verify CORS compliance with the destination server. All modern browsers, according to the same-origin policy security model, designate requests with custom headers as "to be preflighted". When the API requires a custom header, you know that the request must have been preflighted if it came from a browser.

The header can be any arbitrary key-value pair, as long as it does not conflict with existing headers. Empty value is also acceptable.

```
X-CSRF-HEADER=1

```

When handling the request, the API checks for the existence of this header. If the header does not exist, the backend rejects the request as potential forgery. Employing a custom header allows to reject [simple requests](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests) that browsers do not designate as "to be preflighted" and permit them to be sent to any origin.

In order to enable CSRF protection you need to add `CsrfHeaderMiddleware` to the [`MiddlewareDispatcher`](https://github.com/yiisoft/middleware-dispatcher) configuration:

```
$middlewareDispatcher = $injector->make(MiddlewareDispatcher::class);
$middlewareDispatcher = $middlewareDispatcher->withMiddlewares([
    ErrorCatcher::class,
    CsrfHeaderMiddleware::class, //  [
        'withMiddlewares()' => [[
            ErrorCatcher::class,
            CsrfHeaderMiddleware::class, //  static function (RouteCollectorInterface $collector) use ($config) {
        $collector
            ->middleware(CsrfHeaderMiddleware::class) // addGroup(Group::create(null)->routes($routes));

        return new RouteCollection($collector);
    },
];
```

By default, `CsrfHeaderMiddleware` considers only `GET`, `HEAD`, `POST` methods as unsafe operations. Requests with other HTTP methods trigger CORS preflight and do not require CSRF header validation. You can change this behavior as follows:

```
use Yiisoft\Csrf\CsrfHeaderMiddleware;
use Yiisoft\Http\Method;

$csrfHeaderMiddleware = $container->get(CsrfHeaderMiddleware::class);

// Returns a new instance with the specified list of unsafe methods.
$csrfHeaderMiddleware = $csrfHeaderMiddleware->withUnsafeMethods([Method::POST]);

// Returns a new instance with the specified header name.
$csrfHeaderMiddleware = $csrfHeaderMiddleware->withHeaderName('X-CSRF-PROTECTION');
```

or define the `CsrfHeaderMiddleware` configuration in the [DI container](https://github.com/yiisoft/di):

```
// config/web/di/csrf-header.php
use Yiisoft\Csrf\CsrfHeaderMiddleware;
use Yiisoft\Http\Method;

return [
    CsrfHeaderMiddleware::class => [
        'withUnsafeMethods()' => [[Method::POST]],
        'withHeaderName()' => ['X-CSRF-PROTECTION'],
    ],
];
```

The use of a custom request header for CSRF protection is based on the CORS Protocol. Thus, you **must** configure the CORS module to allow or deny cross-origin access to the backend API.

> **Warning**
>
> `CsrfHeaderMiddleware` can be used to prevent forgery of same-origin requests and requests from the list of specific origins only.

### Protecting same-origin requests

[](#protecting-same-origin-requests)

In this scenario:

- AJAX/SPA frontend and API backend have the same origin.
- Cross-origin requests to the API server are denied.
- Simple CORS requests must be restricted.

#### Configure CORS module

[](#configure-cors-module)

- Responses to a CORS preflight requests **must not** contain CORS headers.
- Responses to an actual requests **must not** contain CORS headers.

#### Configure middlewares stack

[](#configure-middlewares-stack)

Add `CsrfHeaderMiddleware` to the [`MiddlewareDispatcher`](https://github.com/yiisoft/middleware-dispatcher) configuration:

```
$middlewareDispatcher = $injector->make(MiddlewareDispatcher::class);
$middlewareDispatcher = $middlewareDispatcher->withMiddlewares([
    ErrorCatcher::class,
    CsrfHeaderMiddleware::class, // get(RouteCollectorInterface::class);
$collector->addGroup(
    Group::create('/api')
        ->middleware(CsrfHeaderMiddleware::class) // routes($routes)
);
```

#### Configure frontend requests

[](#configure-frontend-requests)

On the frontend add to the `GET`, `HEAD`, `POST` requests a custom header defined in the `CsrfHeaderMiddleware` with an empty or random value.

```
let response = fetch('https://example.com/api/whoami', {
  headers: {
    "X-CSRF-HEADER": crypto.randomUUID()
  }
});
```

### Protecting requests from the list of specific origins

[](#protecting-requests-from-the-list-of-specific-origins)

In this scenario:

- AJAX/SPA frontend and API backend have different origins.
- Allow cross origin requests to the API server from the list of specific origins only.
- Simple CORS requests must be restricted.

#### Configure CORS module

[](#configure-cors-module-1)

- A successful responses to a CORS preflight requests **must** contain appropriate CORS headers.
- Responses to an actual requests **must** contain appropriate CORS headers.
- Value of the CORS header `Access-Control-Allow-Origin` **must** contain origin from the predefined list.

```
// assuming frontend origin is https://example.com and backend origin is https://api.example.com
Access-Control-Allow-Origin: https://example.com

```

#### Configure middlewares stack

[](#configure-middlewares-stack-1)

Add `CsrfHeaderMiddleware` to the [`MiddlewareDispatcher`](https://github.com/yiisoft/middleware-dispatcher) configuration:

```
$middlewareDispatcher = $injector->make(MiddlewareDispatcher::class);
$middlewareDispatcher = $middlewareDispatcher->withMiddlewares([
    ErrorCatcher::class,
    CsrfHeaderMiddleware::class, // get(RouteCollectorInterface::class);
$collector->addGroup(
    Group::create('/api')
        ->middleware(CsrfHeaderMiddleware::class) // routes($routes)
);
```

#### Configure frontend requests

[](#configure-frontend-requests-1)

On the frontend add to the `GET`, `HEAD`, `POST` requests a custom header defined in the `CsrfHeaderMiddleware` with an empty or random value.

```
let response = fetch('https://api.example.com/whoami', {
  headers: {
    "X-CSRF-HEADER": crypto.randomUUID()
  }
});
```

### Protecting requests passed from any origin

[](#protecting-requests-passed-from-any-origin)

In this scenario:

- AJAX/SPA frontend and API backend have different origins.
- Allow cross origin requests to the API server from any origin.
- All requests are considered unsafe and **must** be protected against CSRF with CSRF-token.

#### Configure CORS module

[](#configure-cors-module-2)

- A successful responses to a CORS preflight requests **must** contain appropriate CORS headers.
- Responses to an actual requests **must** contain appropriate CORS headers.
- The CORS header `Access-Control-Allow-Origin` has the same value as `Origin` header in the request.

```
$frontendOrigin = $request->getOrigin();

Access-Control-Allow-Origin: $frontendOrigin

```

#### Configure middlewares stack

[](#configure-middlewares-stack-2)

By default, `CsrfTokenMiddleware` considers `GET`, `HEAD`, `OPTIONS` methods as safe operations and doesn't perform CSRF validation. In JavaScript-based apps, requests are made programmatically; therefore, to increase application protection, the only `OPTIONS` method can be considered safe and need not be appended with a CSRF token header.

Configure `CsrfTokenMiddleware` safe methods:

```
use Yiisoft\Csrf\CsrfTokenMiddleware;
use Yiisoft\Http\Method;

$csrfTokenMiddleware = $container->get(CsrfTokenMiddleware::class);
$csrfTokenMiddleware = $csrfTokenMiddleware->withSafeMethods([Method::OPTIONS]);
```

or in the [DI container](https://github.com/yiisoft/di):

```
// config/web/di/csrf-token.php
use Yiisoft\Csrf\CsrfTokenMiddleware;
use Yiisoft\Http\Method;

return [
    CsrfTokenMiddleware::class => [
        'withSafeMethods()' => [[Method::OPTIONS]],
    ],
];
```

Add `CsrfTokenMiddleware` to the [`MiddlewareDispatcher`](https://github.com/yiisoft/middleware-dispatcher) configuration:

```
$middlewareDispatcher = $injector->make(MiddlewareDispatcher::class);
$middlewareDispatcher = $middlewareDispatcher->withMiddlewares([
    ErrorCatcher::class,
    SessionMiddleware::class,
    CsrfTokenMiddleware::class, // get(RouteCollectorInterface::class);
$collector->addGroup(
    Group::create('/api')
        ->middleware(CsrfTokenMiddleware::class) // routes($routes)
);
```

#### Configure routes

[](#configure-routes)

Create a route for acquiring CSRF-tokens from the frontend application to the [router](https://github.com/yiisoft/router) configuration.

```
use Psr\Http\Message\ResponseFactoryInterface;
use Psr\Http\Message\ResponseInterface;
use Yiisoft\Http\Header;
use Yiisoft\Http\Method;
use Yiisoft\Router\Route;

Route::options('/csrf-token')
    ->action(static function (
        ResponseFactoryInterface $responseFactory,
        CsrfTokenInterface $token
    ): ResponseInterface {
        $tokenValue = $token->getValue();

        $response = $responseFactory->createResponse()
            ->withHeader(Header::ALLOW, Method::OPTIONS)
            ->withHeader('X-CSRF-TOKEN', $tokenValue);

        $response->getBody()->write($tokenValue);

        return $response;
    }),
```

#### Configure frontend requests

[](#configure-frontend-requests-2)

On the frontend first make a request to the configured endpoint and acquire a CSRF-token to use it in the subsequent requests.

```
let response = await fetch('https://api.example.com/csrf-token');

let csrfToken = await response.text();
// OR
let csrfToken = response.headers.get('X-CSRF-TOKEN');
```

Add to all requests a custom header defined in the `CsrfTokenMiddleware` with acquired CSRF-token value.

```
let response = fetch('https://api.example.com/whoami', {
  headers: {
    "X-CSRF-TOKEN": csrfToken
  }
});
```

Documentation
-------------

[](#documentation)

- [Internals](docs/internals.md)

If you need help or have a question, the [Yii Forum](https://forum.yiiframework.com/c/yii-3-0/63) is a good place for that. You may also check out other [Yii Community Resources](https://www.yiiframework.com/community).

License
-------

[](#license)

The Yii CSRF Protection Library is free software. It is released under the terms of the BSD License. Please see [`LICENSE`](./LICENSE.md) for more information.

Maintained by [Yii Software](https://www.yiiframework.com/).

Support the project
-------------------

[](#support-the-project)

[![Open Collective](https://camo.githubusercontent.com/a2b15f8e2268d4e3842e00d41ff7a57cce2ad8bd8d8769c5dc4fa05a546a4f62/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4f70656e253230436f6c6c6563746976652d73706f6e736f722d3765616466313f6c6f676f3d6f70656e253230636f6c6c656374697665266c6f676f436f6c6f723d376561646631266c6162656c436f6c6f723d353535353535)](https://opencollective.com/yiisoft)

Follow updates
--------------

[](#follow-updates)

[![Official website](https://camo.githubusercontent.com/d6b0929173e28cc627430d2519ca1853466a70f37395877eaf4820cb3e1e1909/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f506f77657265645f62792d5969695f4672616d65776f726b2d677265656e2e7376673f7374796c653d666c6174)](https://www.yiiframework.com/)[![Twitter](https://camo.githubusercontent.com/d077c362ac639792171af8bc002ee827816733dfc0925f70b557e6d151022226/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f747769747465722d666f6c6c6f772d3144413146323f6c6f676f3d74776974746572266c6f676f436f6c6f723d314441314632266c6162656c436f6c6f723d3535353535353f7374796c653d666c6174)](https://twitter.com/yiiframework)[![Telegram](https://camo.githubusercontent.com/4e38dd12535575c39c65bea7119b95e663abb2d1f4e3d669a27bbda07ef603f0/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f74656c656772616d2d6a6f696e2d3144413146323f7374796c653d666c6174266c6f676f3d74656c656772616d)](https://t.me/yii3en)[![Facebook](https://camo.githubusercontent.com/48204e301b34b29b0815854544f04c337fc0692096cab35e9a1f8c53a42c2307/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f66616365626f6f6b2d6a6f696e2d3144413146323f7374796c653d666c6174266c6f676f3d66616365626f6f6b266c6f676f436f6c6f723d666666666666)](https://www.facebook.com/groups/yiitalk)[![Slack](https://camo.githubusercontent.com/1a3645ba1c97e6684d0349bc478201e1621ba0d3efad516d81035364d442bad7/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f736c61636b2d6a6f696e2d3144413146323f7374796c653d666c6174266c6f676f3d736c61636b)](https://yiiframework.com/go/slack)

###  Health Score

63

—

FairBetter than 99% of packages

Maintenance80

Actively maintained with recent releases

Popularity47

Moderate usage in the ecosystem

Community37

Small or concentrated contributor base

Maturity79

Established project with proven stability

 Bus Factor2

2 contributors hold 50%+ of commits

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~146 days

Total

13

Last Release

196d ago

Major Versions

1.2.0 → 2.0.02023-02-14

PHP version history (4 changes)1.0.0PHP ^7.4|^8.0

2.2.1PHP ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0

2.2.2PHP ~7.4.0 || 8.0 - 8.4

2.2.3PHP ~7.4.0 || 8.0 - 8.5

### Community

Maintainers

![](https://www.gravatar.com/avatar/261a6249c6f605f3956a2fae40fbb813f6b2e1e6f2bf806180c851a965426e54?d=identicon)[cebe](/maintainers/cebe)

![](https://www.gravatar.com/avatar/fc29e4e7068a00fe9b9db37b8aadda1db6020adcacef810461e47b99c2b150e6?d=identicon)[samdark](/maintainers/samdark)

![](https://www.gravatar.com/avatar/ccb75e3312d6bd454ea445ea308139fd185a4ca906ca5df21cc66e6a35de25a3?d=identicon)[SilverFire](/maintainers/SilverFire)

![](https://www.gravatar.com/avatar/99106256c24a8cb23871b99fa90e48f37f1aa71608c185759b7d2a88683a5918?d=identicon)[hiqsol](/maintainers/hiqsol)

---

Top Contributors

[![vjik](https://avatars.githubusercontent.com/u/525501?v=4)](https://github.com/vjik "vjik (40 commits)")[![samdark](https://avatars.githubusercontent.com/u/47294?v=4)](https://github.com/samdark "samdark (30 commits)")[![devanych](https://avatars.githubusercontent.com/u/20116244?v=4)](https://github.com/devanych "devanych (9 commits)")[![xepozz](https://avatars.githubusercontent.com/u/6815714?v=4)](https://github.com/xepozz "xepozz (6 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (5 commits)")[![luizcmarin](https://avatars.githubusercontent.com/u/67489841?v=4)](https://github.com/luizcmarin "luizcmarin (3 commits)")[![roxblnfk](https://avatars.githubusercontent.com/u/4152481?v=4)](https://github.com/roxblnfk "roxblnfk (2 commits)")[![Fantom409](https://avatars.githubusercontent.com/u/14968877?v=4)](https://github.com/Fantom409 "Fantom409 (2 commits)")[![mspirkov](https://avatars.githubusercontent.com/u/63721828?v=4)](https://github.com/mspirkov "mspirkov (2 commits)")[![rustamwin](https://avatars.githubusercontent.com/u/16498265?v=4)](https://github.com/rustamwin "rustamwin (2 commits)")[![terabytesoftw](https://avatars.githubusercontent.com/u/42547589?v=4)](https://github.com/terabytesoftw "terabytesoftw (2 commits)")[![hacan359](https://avatars.githubusercontent.com/u/59626486?v=4)](https://github.com/hacan359 "hacan359 (1 commits)")[![Nex-Otaku](https://avatars.githubusercontent.com/u/2260071?v=4)](https://github.com/Nex-Otaku "Nex-Otaku (1 commits)")[![sankaest](https://avatars.githubusercontent.com/u/21160342?v=4)](https://github.com/sankaest "sankaest (1 commits)")[![solventt](https://avatars.githubusercontent.com/u/46854749?v=4)](https://github.com/solventt "solventt (1 commits)")[![ev-gor](https://avatars.githubusercontent.com/u/177424352?v=4)](https://github.com/ev-gor "ev-gor (1 commits)")[![Tigrov](https://avatars.githubusercontent.com/u/8563175?v=4)](https://github.com/Tigrov "Tigrov (1 commits)")[![viktorprogger](https://avatars.githubusercontent.com/u/7670669?v=4)](https://github.com/viktorprogger "viktorprogger (1 commits)")[![olegbaturin](https://avatars.githubusercontent.com/u/15981018?v=4)](https://github.com/olegbaturin "olegbaturin (1 commits)")[![Arhell](https://avatars.githubusercontent.com/u/26163841?v=4)](https://github.com/Arhell "Arhell (1 commits)")

---

Tags

csrfhacktoberfestmiddlewarepsr-15yii3middlewarepsr-15csrfhmacstatelesssynchronizerbreach

###  Code Quality

TestsPHPUnit

Static AnalysisPsalm, Rector

Type Coverage Yes

### Embed Badge

![Health badge](/badges/yiisoft-csrf/health.svg)

```
[![Health](https://phpackages.com/badges/yiisoft-csrf/health.svg)](https://phpackages.com/packages/yiisoft-csrf)
```

###  Alternatives

[cakephp/cakephp

The CakePHP framework

8.9k19.5M1.8k](/packages/cakephp-cakephp)[typo3/cms

TYPO3 CMS is a free open source Content Management Framework initially created by Kasper Skaarhoj and licensed under GNU/GPL.

1.2k1.9M122](/packages/typo3-cms)[typo3/cms-core

TYPO3 CMS Core

3713.2M5.1k](/packages/typo3-cms-core)[tempest/framework

The PHP framework that gets out of your way.

2.2k34.4k15](/packages/tempest-framework)[spiral/framework

Spiral, High-Performance PHP/Go Framework

2.1k2.2M66](/packages/spiral-framework)[cakephp/authentication

Authentication plugin for CakePHP

1214.1M106](/packages/cakephp-authentication)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
