TYPO3 v15 dev-main snapshot ()
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
namespace TYPO3\CMS\Core\Security;
|
||||
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class RequestToken
|
||||
{
|
||||
use JwtTrait;
|
||||
|
||||
public const PARAM_NAME = '__RequestToken';
|
||||
public const HEADER_NAME = 'X-TYPO3-RequestToken';
|
||||
|
||||
public readonly string $scope;
|
||||
public readonly \DateTimeImmutable $time;
|
||||
/**
|
||||
* @var array<int|string, mixed>
|
||||
*/
|
||||
public readonly array $params;
|
||||
|
||||
/**
|
||||
* Identifier that was used for signing, filled when decoding.
|
||||
*/
|
||||
private ?SecretIdentifier $signingSecretIdentifier = null;
|
||||
|
||||
public static function create(string $scope): self
|
||||
{
|
||||
return GeneralUtility::makeInstance(self::class, $scope);
|
||||
}
|
||||
|
||||
public static function fromHashSignedJwt(string $jwt, SigningSecretInterface|SigningSecretResolver $secret): self
|
||||
{
|
||||
// invokes resolver to retrieve corresponding secret
|
||||
// a hint was stored in the `kid` (keyId) property of the JWT header
|
||||
if ($secret instanceof SigningSecretResolver) {
|
||||
try {
|
||||
$kid = (string)self::decodeJwtHeader($jwt, 'kid');
|
||||
$identifier = SecretIdentifier::fromJson($kid);
|
||||
$secret = $secret->findByIdentifier($identifier);
|
||||
} catch (\Throwable $t) {
|
||||
throw new RequestTokenException('Could not reconstitute request token', 1664202134, $t);
|
||||
}
|
||||
if ($secret === null) {
|
||||
throw new RequestTokenException('Could not reconstitute request token', 1664202135);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$payload = self::decodeJwt($jwt, self::createSigningSecret($secret, RequestToken::class), true);
|
||||
$subject = GeneralUtility::makeInstance(
|
||||
self::class,
|
||||
$payload['scope'] ?? '',
|
||||
\DateTimeImmutable::createFromFormat(\DateTimeImmutable::RFC3339, $payload['time'] ?? null),
|
||||
$payload['params'] ?? []
|
||||
);
|
||||
$subject->signingSecretIdentifier = $secret->getSigningIdentifier();
|
||||
return $subject;
|
||||
} catch (\Throwable $t) {
|
||||
throw new RequestTokenException('Could not reconstitute request token', 1651771352, $t);
|
||||
}
|
||||
}
|
||||
|
||||
public function __construct(string $scope, ?\DateTimeImmutable $time = null, array $params = [])
|
||||
{
|
||||
$this->scope = $scope;
|
||||
// drop microtime, second is the minimum date-interval
|
||||
$this->time = \DateTimeImmutable::createFromFormat(
|
||||
\DateTimeImmutable::RFC3339,
|
||||
($time ?? new \DateTimeImmutable())->format(\DateTimeImmutable::RFC3339)
|
||||
);
|
||||
$this->params = $params;
|
||||
}
|
||||
|
||||
public function toHashSignedJwt(SigningSecretInterface $secret): string
|
||||
{
|
||||
$payload = [
|
||||
'scope' => $this->scope,
|
||||
'time' => $this->time->format(\DateTimeImmutable::RFC3339),
|
||||
'params' => $this->params,
|
||||
];
|
||||
return self::encodeHashSignedJwt(
|
||||
$payload,
|
||||
self::createSigningSecret($secret, RequestToken::class),
|
||||
$secret->getSigningIdentifier()
|
||||
);
|
||||
}
|
||||
|
||||
public function withParams(array $params): self
|
||||
{
|
||||
return GeneralUtility::makeInstance(self::class, $this->scope, $this->time, $params);
|
||||
}
|
||||
|
||||
public function withMergedParams(array $params): self
|
||||
{
|
||||
return $this->withParams(array_merge_recursive($this->params, $params));
|
||||
}
|
||||
|
||||
public function getSigningSecretIdentifier(): ?SecretIdentifier
|
||||
{
|
||||
return $this->signingSecretIdentifier;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user