Skip to content

Commit 04f90e6

Browse files
Copilotsamdark
andauthored
Fix #112: Add "Disabling CSRF protection" article to cookbook (#250)
Co-authored-by: Alexander Makarov <sam@rmcreative.ru>
1 parent 8f325bc commit 04f90e6

File tree

2 files changed

+134
-0
lines changed

2 files changed

+134
-0
lines changed

cookbook/en/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,6 @@ This book conforms to the [Terms of Yii Documentation](https://www.yiiframework.
1414

1515
- [Preface](preface.md)
1616
- [Structuring code by use-case with vertical slices](organizing-code/structuring-by-use-case-with-vertical-slices.md)
17+
- [Disabling CSRF protection](disabling-csrf-protection.md)
1718
- [Sentry integration](sentry-integration.md)
1819
- [Configuring webservers](configuring-webservers/general.md)
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
# Disabling CSRF protection
2+
3+
## What is CSRF protection?
4+
5+
Cross-Site Request Forgery (CSRF) protection is a security mechanism that prevents malicious websites from making
6+
unauthorized requests on behalf of authenticated users. Yii3 includes built-in CSRF protection through
7+
the `Yiisoft\Yii\Web\Middleware\Csrf` middleware.
8+
9+
For a comprehensive understanding of CSRF attacks and protection mechanisms, see
10+
the [Security best practices](../../guide/en/security/best-practices.md#avoiding-csrf) section in the main guide.
11+
12+
## When to disable CSRF protection
13+
14+
While CSRF protection should generally remain enabled for web applications, there are specific scenarios where you might
15+
need to disable it:
16+
17+
### When external systems cannot provide CSRF tokens
18+
19+
When building APIs or handling automated requests from external systems, CSRF protection can interfere with legitimate
20+
requests since these systems cannot provide valid CSRF tokens:
21+
22+
- **Third-party integrations**: External services cannot provide valid CSRF tokens
23+
- **Mobile applications**: Native mobile apps typically don't use cookies or sessions in the same way as web browsers
24+
- **Server-to-server communication**: API endpoints designed for machine-to-machine communication
25+
- **Payment processors**: PayPal, Stripe, and other payment systems send webhook notifications
26+
- **Version control systems**: GitHub, GitLab webhooks for CI/CD pipelines
27+
- **Social media platforms**: Twitter, Facebook webhook notifications
28+
- **Communication services**: Slack, Discord bot integrations
29+
30+
## How to disable CSRF protection
31+
32+
First, you need to remove CSRF middleware from your main application middleware list in `config/web/di/application.php`:
33+
34+
```php
35+
return [
36+
Application::class => [
37+
'__construct()' => [
38+
'dispatcher' => DynamicReference::to([
39+
'class' => MiddlewareDispatcher::class,
40+
'withMiddlewares()' => [
41+
[
42+
ErrorCatcher::class,
43+
SessionMiddleware::class,
44+
CsrfTokenMiddleware::class, // <- Remove this line
45+
```
46+
47+
Now, if you need to leave CSRF on for specific routes or route groups, you can do so by adding the `CsrfMiddleware`
48+
middleware to the router configuration in `config/common/routes.php`. For a group that would be the following:
49+
50+
```php
51+
return [
52+
Group::create()
53+
->middleware(CsrfTokenMiddleware::class)
54+
->routes(
55+
```
56+
57+
For a single route, you can add the middleware directly to the route:
58+
59+
```php
60+
Route::methods([Method::GET, Method::POST], '/say[/{test}]')
61+
->action(\App\Controller\Echo\Action::class)
62+
->name('echo/say')
63+
->middleware(CsrfTokenMiddleware::class)
64+
```
65+
66+
67+
## Security considerations
68+
69+
When disabling CSRF protection, keep these security considerations in mind:
70+
71+
### Alternative authentication methods
72+
73+
For API endpoints, implement proper authentication mechanisms:
74+
75+
- **API keys**: Require API keys for authentication
76+
- **Bearer tokens**: Use JWT or similar token-based authentication
77+
- **OAuth 2.0**: Implement OAuth 2.0 for third-party access
78+
- **IP whitelisting**: Restrict access to known IP addresses for webhooks
79+
80+
### Request validation
81+
82+
Implement additional validation for requests without CSRF protection:
83+
84+
- **Signature verification**: Verify webhook signatures (e.g., GitHub's X-Hub-Signature)
85+
- **Timestamp validation**: Check request timestamps to prevent replay attacks
86+
- **Rate limiting**: Implement rate limiting to prevent abuse
87+
- **Input validation**: Strictly validate all input parameters
88+
89+
### Example: Webhook signature verification
90+
91+
```php
92+
<?php
93+
94+
declare(strict_types=1);
95+
96+
use Psr\Http\Message\ResponseInterface;
97+
use Psr\Http\Message\ServerRequestInterface;
98+
99+
final class WebhookController
100+
{
101+
public function payment(ServerRequestInterface $request): ResponseInterface
102+
{
103+
// Verify webhook signature
104+
$signature = $request->getHeaderLine('X-Webhook-Signature');
105+
$payload = (string) $request->getBody();
106+
$expectedSignature = hash_hmac('sha256', $payload, $this->webhookSecret);
107+
108+
if (!hash_equals($signature, $expectedSignature)) {
109+
throw new \RuntimeException('Invalid webhook signature');
110+
}
111+
112+
// Process webhook payload
113+
// ...
114+
}
115+
}
116+
```
117+
118+
## Best practices
119+
120+
1. **Minimize exposure**: Only disable CSRF protection where absolutely necessary
121+
2. **Use HTTPS**: Always use HTTPS for API endpoints and webhooks
122+
3. **Monitor logs**: Log all requests to API endpoints for security monitoring
123+
4. **Regular security audits**: Periodically review your API endpoints and their security measures
124+
5. **Documentation**: Clearly document which endpoints have CSRF protection disabled and why
125+
126+
## Conclusion
127+
128+
While CSRF protection is crucial for web applications, there are legitimate scenarios where it needs to be disabled,
129+
particularly for external APIs and webhooks. When disabling CSRF protection, always implement alternative security
130+
measures and follow security best practices to maintain the overall security of your application.
131+
132+
Remember that disabling CSRF protection increases security risks, so careful consideration and proper implementation
133+
of alternative security measures are essential.

0 commit comments

Comments
 (0)