Skip to content

Commit f321136

Browse files
committed
Request::isSameSite() uses isFrom() and is deprecated; strict cookie sent only without Sec-Fetch-Site
1 parent ea7cf1c commit f321136

4 files changed

Lines changed: 31 additions & 5 deletions

File tree

src/Http/Helpers.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,10 +113,13 @@ public static function ipMatch(string $ip, string $mask): bool
113113

114114

115115
/**
116-
* Sends the strict same-site cookie used to detect same-site requests.
116+
* Sends the SameSite=Strict cookie used as a fallback for detecting same-site requests
117+
* in browsers that don't support the Sec-Fetch-Site header (Safari < 16.4).
117118
*/
118119
public static function initCookie(IRequest $request, IResponse $response): void
119120
{
120-
$response->setCookie(self::StrictCookieName, '1', null, '/', sameSite: IResponse::SameSiteStrict);
121+
if ($request->getHeader('Sec-Fetch-Site') === null) {
122+
$response->setCookie(self::StrictCookieName, '1', null, '/', sameSite: IResponse::SameSiteStrict);
123+
}
121124
}
122125
}

src/Http/IRequest.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
/**
1212
* HTTP request contract providing access to URL, headers, cookies, uploaded files, and body.
1313
* @method ?UrlImmutable getReferer() Returns the referrer URL.
14-
* @method bool isSameSite() Checks whether the request is coming from the same site.
1514
* @method bool isFrom(self::From*|list<self::From*> $site, string|list<string>|null $dest = null, ?bool $user = null)
1615
*/
1716
interface IRequest

src/Http/Request.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,11 +230,13 @@ public function isSecured(): bool
230230

231231

232232
/**
233-
* Checks whether the request is coming from the same site and was initiated by clicking on a link.
233+
* Checks whether the request originated from your own site (same-site), i.e. it was not
234+
* triggered from a foreign website. Serves as a CSRF-like protection for forms and signals.
235+
* @deprecated use isFrom()
234236
*/
235237
public function isSameSite(): bool
236238
{
237-
return isset($this->cookies[Helpers::StrictCookieName]);
239+
return $this->isFrom([self::FromSameSite, self::FromSameOrigin]);
238240
}
239241

240242

tests/Http/Request.isFrom.phpt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,3 +123,25 @@ test('cookie fallback not used when Sec-Fetch-Site present', function () {
123123
Assert::false($request->isFrom('same-origin'));
124124
Assert::true($request->isFrom('cross-site'));
125125
});
126+
127+
128+
test('isSameSite() via Sec-Fetch-Site', function () {
129+
foreach (['same-origin', 'same-site', 'none'] as $site) {
130+
$request = new Http\Request(new Http\UrlScript, headers: ['Sec-Fetch-Site' => $site]);
131+
Assert::true($request->isSameSite(), $site);
132+
}
133+
134+
$request = new Http\Request(new Http\UrlScript, headers: ['Sec-Fetch-Site' => 'cross-site']);
135+
Assert::false($request->isSameSite());
136+
});
137+
138+
139+
test('isSameSite() via cookie fallback', function () {
140+
$request = new Http\Request(new Http\UrlScript, cookies: [
141+
Http\Helpers::StrictCookieName => '1',
142+
]);
143+
Assert::true($request->isSameSite());
144+
145+
$request = new Http\Request(new Http\UrlScript);
146+
Assert::false($request->isSameSite());
147+
});

0 commit comments

Comments
 (0)