Skip to content

Commit 33b404a

Browse files
committed
Don't throw a BadRequestHttpException right away if there's an invalid token
Resolves #18000
1 parent c86c2ed commit 33b404a

File tree

3 files changed

+32
-16
lines changed

3 files changed

+32
-16
lines changed

CHANGELOG-WIP.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
- Added `craft\services\Structure::EVENT_AFTER_UPDATE_ELEMENT`.
6464
- Added `craft\services\Structure::EVENT_BEFORE_UPDATE_ELEMENT`.
6565
- Added `craft\web\GqlResponseFormatter`.
66+
- Added `craft\web\Request::getHasInvalidToken()`.
6667
- Added `craft\web\Response::FORMAT_GQL`.
6768
- Added `craft\web\twig\nodes\BaseNode`.
6869
- Added `Craft.BaseElementIndex::asyncSelectDefaultSource()`.
@@ -97,4 +98,5 @@
9798
- Improved element query performance. ([#17850](https://github.com/craftcms/cms/pull/17850))
9899
- Fixed a bug where elements with unsaved changes could show outdated attribute/field values within element index tables, chips, and cards throughout the control panel. ([#17915](https://github.com/craftcms/cms/pull/17915))
99100
- Fixed a bug where Table fields with the “Static Rows” setting enabled would lose track of which values belonged to which row headings, if the “Default Values” table was reordered. ([#17090](https://github.com/craftcms/cms/issues/17090))
101+
- Fixed a bug where requests with invalid tokens would throw an exception before the application was fully initialized, which could lead to other errors. ([#18000](https://github.com/craftcms/cms/issues/18000))
100102
- Updated Twig to 3.21. ([#17603](https://github.com/craftcms/cms/discussions/17603))

src/web/Application.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,11 @@ public function init(): void
107107

108108
$this->_postInit();
109109

110+
// If there's an invalid token on the request, throw an exception now
111+
if ($this->getRequest()->getHasInvalidToken()) {
112+
throw new BadRequestHttpException('Invalid token');
113+
}
114+
110115
// Process resource requests before we do anything to establish the user session
111116
$this->_processResourceRequest();
112117

src/web/Request.php

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,12 @@ class Request extends \yii\web\Request
188188
*/
189189
private bool $_setBodyParams = false;
190190

191+
/**
192+
* @var bool Whether the request has an invalid token.
193+
* @see getHasInvalidToken())
194+
*/
195+
private bool $_hasInvalidToken;
196+
191197
/**
192198
* @var bool|null Whether the request initially had a token
193199
* @see getHadToken()
@@ -493,7 +499,6 @@ public function getPageNum(): int
493499
* Returns whether the request initially had a token.
494500
*
495501
* @return bool
496-
* @throws BadRequestHttpException
497502
* @since 3.6.0
498503
*/
499504
public function getHadToken(): bool
@@ -509,7 +514,6 @@ public function getHadToken(): bool
509514
* default), or an `X-Craft-Token` HTTP header on the request.
510515
*
511516
* @return string|null The token, or `null` if there isn’t one.
512-
* @throws BadRequestHttpException if an invalid token is supplied
513517
* @see Tokens::createToken()
514518
* @see Controller::requireToken()
515519
*/
@@ -528,34 +532,39 @@ public function getToken(): ?string
528532
public function setToken(?string $token): void
529533
{
530534
// Make sure $this->_hadToken has been set
531-
try {
532-
$this->_findToken();
533-
} catch (BadRequestHttpException) {
534-
}
535+
$this->_findToken();
535536

536537
$this->_token = $token;
537538
}
538539

539540
/**
540-
* Looks for a token on the request.
541+
* Returns whether there is an invalid token on the request.
541542
*
542-
* @throws BadRequestHttpException
543+
* @return bool
544+
* @since 5.9.0
545+
*/
546+
public function getHasInvalidToken(): bool
547+
{
548+
$this->_findToken();
549+
return $this->_hasInvalidToken;
550+
}
551+
552+
/**
553+
* Looks for a token on the request.
543554
*/
544555
private function _findToken(): void
545556
{
546-
if (isset($this->_hadToken)) {
557+
if (isset($this->_hasInvalidToken)) {
547558
return;
548559
}
549560

550-
$this->_token = ($this->getQueryParam($this->generalConfig->tokenParam) ?? $this->getHeaders()->get('X-Craft-Token')) ?: null;
561+
$token = ($this->getQueryParam($this->generalConfig->tokenParam) ?? $this->getHeaders()->get('X-Craft-Token')) ?: null;
562+
$this->_hasInvalidToken = $token && !preg_match('/^[A-Za-z0-9_-]+$/', $token);
551563

552-
if ($this->_token && !preg_match('/^[A-Za-z0-9_-]+$/', $this->_token)) {
553-
$this->_token = null;
554-
$this->_hadToken = false;
555-
throw new BadRequestHttpException('Invalid token');
564+
if (!$this->_hasInvalidToken) {
565+
$this->_token = $token;
566+
$this->_hadToken = $token !== null;
556567
}
557-
558-
$this->_hadToken = isset($this->_token);
559568
}
560569

561570
/**

0 commit comments

Comments
 (0)