|
23 | 23 | * |
24 | 24 | * This manager is designed to be stateless and compatible with HTTP-caching. |
25 | 25 | * |
26 | | - * First, we validate the source of the request using the Origin/Referer headers. This relies |
27 | | - * on the app being able to know its own target origin. Don't miss configuring your reverse proxy to |
28 | | - * send the X-Forwarded-* / Forwarded headers if you're behind one. |
| 26 | + * Requests are considered secure when either: |
| 27 | + * - the Sec-Fetch-Site header contains 'same-origin'; |
| 28 | + * - the Origin or Referer headers contain the same origin as the request; |
| 29 | + * - a special token was double-submitted in the request payload and as a cookie and/or a header. |
29 | 30 | * |
30 | | - * Then, we validate the request using a cookie and a CsrfToken. If the cookie is found, it should |
31 | | - * contain the same value as the CsrfToken. A JavaScript snippet on the client side is responsible |
32 | | - * for performing this double-submission. The token value should be regenerated on every request |
33 | | - * using a cryptographically secure random generator. |
| 31 | + * The check using the Origin/Referer headers relies on the app being able to know its own target |
| 32 | + * origin. Don't miss configuring your reverse proxy to send the X-Forwarded-* / Forwarded headers |
| 33 | + * if you're behind one. |
34 | 34 | * |
35 | | - * If either double-submit or Origin/Referer headers are missing, it typically indicates that |
36 | | - * JavaScript is disabled on the client side, or that the JavaScript snippet was not properly |
37 | | - * implemented, or that the Origin/Referer headers were filtered out. |
38 | | - * |
39 | | - * Requests lacking both double-submit and origin information are deemed insecure. |
| 35 | + * The check relying on the double-submit requires a JavaScript snippet on the client side, |
| 36 | + * responsible for generating a cryptographically-secure random token and attaching it to the request |
| 37 | + * payload and as a cookie and/or a header. This check is meant to cover the case where neither |
| 38 | + * Sec-Fetch-Site, nor Origin/Referer headers are present. |
40 | 39 | * |
41 | 40 | * When a session is found, a behavioral check is added to ensure that the validation method does not |
42 | | - * downgrade from double-submit to origin checks. This prevents attackers from exploiting potentially |
43 | | - * less secure validation methods once a more secure method has been confirmed as functional. |
| 41 | + * downgrade from double-submit to origin checks, and vice versa. This prevents attackers from |
| 42 | + * exploiting potentially less secure validation methods once a more secure method has been confirmed |
| 43 | + * as functional. |
44 | 44 | * |
45 | 45 | * On HTTPS connections, the cookie is prefixed with "__Host-" to prevent it from being forged on an |
46 | 46 | * HTTP channel. On the JS side, the cookie should be set with samesite=strict to strengthen the CSRF |
|
50 | 50 | * cookie. This makes it harder for an attacker to forge a request, though it may also pose challenges |
51 | 51 | * when setting the header depending on the client-side framework in use. |
52 | 52 | * |
53 | | - * When a fallback CSRF token manager is provided, only tokens listed in the $tokenIds argument will be |
54 | | - * managed by this manager. All other tokens will be delegated to the fallback manager. |
| 53 | + * When a fallback CSRF token manager is provided, only tokens listed in the $tokenIds argument will |
| 54 | + *bemanaged by this manager. All other tokens will be delegated to the fallback manager. |
55 | 55 | * |
56 | 56 | * @author Nicolas Grekas <p@tchwork.com> |
57 | 57 | */ |
@@ -235,6 +235,10 @@ public function onKernelResponse(ResponseEvent $event): void |
235 | 235 | */ |
236 | 236 | privatefunctionisValidOrigin(Request$request): ?bool |
237 | 237 | { |
| 238 | +if (null !==$header =$request->headers->get('Sec-Fetch-Site')) { |
| 239 | +return'same-origin' ===$header; |
| 240 | + } |
| 241 | + |
238 | 242 | $target =$request->getSchemeAndHttpHost().'/'; |
239 | 243 | $source ='null'; |
240 | 244 |
|
|