17
17
*/
18
18
class SetCookie implements MultipleHeaderInterface
19
19
{
20
+ /**
21
+ * Cookie will not be sent for any cross-domain requests whatsoever.
22
+ * Even if the user simply navigates to the target site with a regular link, the cookie will not be sent.
23
+ */
24
+ const SAME_SITE_STRICT = 'Strict ' ;
25
+
26
+ /**
27
+ * Cookie will not be passed for any cross-domain requests unless it's a regular link that navigates user
28
+ * to the target site.
29
+ * Other requests methods (such as POST and PUT) and XHR requests will not contain this cookie.
30
+ */
31
+ const SAME_SITE_LAX = 'Lax ' ;
32
+
33
+ /**
34
+ * Cookie will be sent with same-site and cross-site requests.
35
+ */
36
+ const SAME_SITE_NONE = 'None ' ;
37
+
38
+ /**
39
+ * @internal
40
+ */
41
+ const SAME_SITE_ALLOWED_VALUES = [
42
+ self ::SAME_SITE_STRICT ,
43
+ self ::SAME_SITE_LAX ,
44
+ self ::SAME_SITE_NONE ,
45
+ ];
46
+
20
47
/**
21
48
* Cookie name
22
49
*
@@ -85,6 +112,11 @@ class SetCookie implements MultipleHeaderInterface
85
112
*/
86
113
protected $ httponly ;
87
114
115
+ /**
116
+ * @var string|null
117
+ */
118
+ protected $ sameSite ;
119
+
88
120
/**
89
121
* @var bool
90
122
*/
@@ -152,6 +184,9 @@ public static function fromString($headerLine, $bypassHeaderFieldName = false)
152
184
case 'maxage ' :
153
185
$ header ->setMaxAge ($ headerValue );
154
186
break ;
187
+ case 'samesite ' :
188
+ $ header ->setSameSite ($ headerValue );
189
+ break ;
155
190
default :
156
191
// Intentionally omitted
157
192
}
@@ -199,6 +234,7 @@ public static function fromString($headerLine, $bypassHeaderFieldName = false)
199
234
* @param bool $httponly
200
235
* @param int|null $maxAge
201
236
* @param int|null $version
237
+ * @param string|null $sameSite
202
238
*/
203
239
public function __construct (
204
240
$ name = null ,
@@ -209,7 +245,8 @@ public function __construct(
209
245
$ secure = false ,
210
246
$ httponly = false ,
211
247
$ maxAge = null ,
212
- $ version = null
248
+ $ version = null ,
249
+ $ sameSite = null
213
250
) {
214
251
$ this ->type = 'Cookie ' ;
215
252
@@ -221,7 +258,8 @@ public function __construct(
221
258
->setExpires ($ expires )
222
259
->setPath ($ path )
223
260
->setSecure ($ secure )
224
- ->setHttpOnly ($ httponly );
261
+ ->setHttpOnly ($ httponly )
262
+ ->setSameSite ($ sameSite );
225
263
}
226
264
227
265
/**
@@ -298,6 +336,11 @@ public function getFieldValue()
298
336
$ fieldValue .= '; HttpOnly ' ;
299
337
}
300
338
339
+ $ sameSite = $ this ->getSameSite ();
340
+ if ($ sameSite !== null && in_array ($ sameSite , self ::SAME_SITE_ALLOWED_VALUES , true )) {
341
+ $ fieldValue .= '; SameSite= ' . $ sameSite ;
342
+ }
343
+
301
344
return $ fieldValue ;
302
345
}
303
346
@@ -560,6 +603,31 @@ public function isSessionCookie()
560
603
return ($ this ->expires === null );
561
604
}
562
605
606
+ /**
607
+ * @return string|null
608
+ */
609
+ public function getSameSite ()
610
+ {
611
+ return $ this ->sameSite ;
612
+ }
613
+
614
+ /**
615
+ * @param string|null $sameSite
616
+ * @return $this
617
+ * @throws Exception\InvalidArgumentException
618
+ */
619
+ public function setSameSite ($ sameSite )
620
+ {
621
+ if ($ sameSite !== null && ! in_array ($ sameSite , self ::SAME_SITE_ALLOWED_VALUES , true )) {
622
+ throw new Exception \InvalidArgumentException (sprintf (
623
+ 'Invalid value provided for SameSite directive: "%s"; expected one of: Strict, Lax or None ' ,
624
+ is_scalar ($ sameSite ) ? $ sameSite : gettype ($ sameSite )
625
+ ));
626
+ }
627
+ $ this ->sameSite = $ sameSite ;
628
+ return $ this ;
629
+ }
630
+
563
631
/**
564
632
* Check whether the value for this cookie should be quoted
565
633
*
0 commit comments