first commit
This commit is contained in:
28
libraries/vendor/web-token/jwt-signature/Algorithm/MacAlgorithm.php
vendored
Normal file
28
libraries/vendor/web-token/jwt-signature/Algorithm/MacAlgorithm.php
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Jose\Component\Signature\Algorithm;
|
||||
|
||||
use Jose\Component\Core\Algorithm;
|
||||
use Jose\Component\Core\JWK;
|
||||
|
||||
interface MacAlgorithm extends Algorithm
|
||||
{
|
||||
/**
|
||||
* Sign the input.
|
||||
*
|
||||
* @param JWK $key The private key used to hash the data
|
||||
* @param string $input The input
|
||||
*/
|
||||
public function hash(JWK $key, string $input): string;
|
||||
|
||||
/**
|
||||
* Verify the signature of data.
|
||||
*
|
||||
* @param JWK $key The private key used to hash the data
|
||||
* @param string $input The input
|
||||
* @param string $signature The signature to verify
|
||||
*/
|
||||
public function verify(JWK $key, string $input, string $signature): bool;
|
||||
}
|
||||
28
libraries/vendor/web-token/jwt-signature/Algorithm/SignatureAlgorithm.php
vendored
Normal file
28
libraries/vendor/web-token/jwt-signature/Algorithm/SignatureAlgorithm.php
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Jose\Component\Signature\Algorithm;
|
||||
|
||||
use Jose\Component\Core\Algorithm;
|
||||
use Jose\Component\Core\JWK;
|
||||
|
||||
interface SignatureAlgorithm extends Algorithm
|
||||
{
|
||||
/**
|
||||
* Sign the input.
|
||||
*
|
||||
* @param JWK $key The private key used to sign the data
|
||||
* @param string $input The input
|
||||
*/
|
||||
public function sign(JWK $key, string $input): string;
|
||||
|
||||
/**
|
||||
* Verify the signature of data.
|
||||
*
|
||||
* @param JWK $key The private key used to sign the data
|
||||
* @param non-empty-string $input The input
|
||||
* @param non-empty-string $signature The signature to verify
|
||||
*/
|
||||
public function verify(JWK $key, string $input, string $signature): bool;
|
||||
}
|
||||
123
libraries/vendor/web-token/jwt-signature/JWS.php
vendored
Normal file
123
libraries/vendor/web-token/jwt-signature/JWS.php
vendored
Normal file
@ -0,0 +1,123 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Jose\Component\Signature;
|
||||
|
||||
use function count;
|
||||
use InvalidArgumentException;
|
||||
use Jose\Component\Core\JWT;
|
||||
|
||||
class JWS implements JWT
|
||||
{
|
||||
/**
|
||||
* @var Signature[]
|
||||
*/
|
||||
private array $signatures = [];
|
||||
|
||||
public function __construct(
|
||||
private readonly ?string $payload,
|
||||
private readonly ?string $encodedPayload = null,
|
||||
private readonly bool $isPayloadDetached = false
|
||||
) {
|
||||
}
|
||||
|
||||
public function getPayload(): ?string
|
||||
{
|
||||
return $this->payload;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the payload is detached.
|
||||
*/
|
||||
public function isPayloadDetached(): bool
|
||||
{
|
||||
return $this->isPayloadDetached;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Base64Url encoded payload. If the payload is detached, this method returns null.
|
||||
*/
|
||||
public function getEncodedPayload(): ?string
|
||||
{
|
||||
if ($this->isPayloadDetached() === true) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->encodedPayload;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the signatures associated with the JWS.
|
||||
*
|
||||
* @return Signature[]
|
||||
*/
|
||||
public function getSignatures(): array
|
||||
{
|
||||
return $this->signatures;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the signature at the given index.
|
||||
*/
|
||||
public function getSignature(int $id): Signature
|
||||
{
|
||||
if (isset($this->signatures[$id])) {
|
||||
return $this->signatures[$id];
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException('The signature does not exist.');
|
||||
}
|
||||
|
||||
/**
|
||||
* This method adds a signature to the JWS object. Its returns a new JWS object.
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @param array{alg?: string, string?: mixed} $protectedHeader
|
||||
* @param array{alg?: string, string?: mixed} $header
|
||||
*/
|
||||
public function addSignature(
|
||||
string $signature,
|
||||
array $protectedHeader,
|
||||
?string $encodedProtectedHeader,
|
||||
array $header = []
|
||||
): self {
|
||||
$jws = clone $this;
|
||||
$jws->signatures[] = new Signature($signature, $protectedHeader, $encodedProtectedHeader, $header);
|
||||
|
||||
return $jws;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of signature associated with the JWS.
|
||||
*/
|
||||
public function countSignatures(): int
|
||||
{
|
||||
return count($this->signatures);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method splits the JWS into a list of JWSs. It is only useful when the JWS contains more than one signature
|
||||
* (JSON General Serialization).
|
||||
*
|
||||
* @return JWS[]
|
||||
*/
|
||||
public function split(): array
|
||||
{
|
||||
$result = [];
|
||||
foreach ($this->signatures as $signature) {
|
||||
$jws = new self($this->payload, $this->encodedPayload, $this->isPayloadDetached);
|
||||
$jws = $jws->addSignature(
|
||||
$signature->getSignature(),
|
||||
$signature->getProtectedHeader(),
|
||||
$signature->getEncodedProtectedHeader(),
|
||||
$signature->getHeader()
|
||||
);
|
||||
|
||||
$result[] = $jws;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
223
libraries/vendor/web-token/jwt-signature/JWSBuilder.php
vendored
Normal file
223
libraries/vendor/web-token/jwt-signature/JWSBuilder.php
vendored
Normal file
@ -0,0 +1,223 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Jose\Component\Signature;
|
||||
|
||||
use function array_key_exists;
|
||||
use function count;
|
||||
use function in_array;
|
||||
use InvalidArgumentException;
|
||||
use function is_array;
|
||||
use Jose\Component\Core\Algorithm;
|
||||
use Jose\Component\Core\AlgorithmManager;
|
||||
use Jose\Component\Core\JWK;
|
||||
use Jose\Component\Core\Util\JsonConverter;
|
||||
use Jose\Component\Core\Util\KeyChecker;
|
||||
use Jose\Component\Signature\Algorithm\MacAlgorithm;
|
||||
use Jose\Component\Signature\Algorithm\SignatureAlgorithm;
|
||||
use LogicException;
|
||||
use ParagonIE\ConstantTime\Base64UrlSafe;
|
||||
use RuntimeException;
|
||||
|
||||
class JWSBuilder
|
||||
{
|
||||
protected ?string $payload = null;
|
||||
|
||||
protected bool $isPayloadDetached = false;
|
||||
|
||||
/**
|
||||
* @var array<array{
|
||||
* header: array<string, mixed>,
|
||||
* protected_header: array<string, mixed>,
|
||||
* signature_key: JWK,
|
||||
* signature_algorithm: Algorithm
|
||||
* }>
|
||||
*/
|
||||
protected array $signatures = [];
|
||||
|
||||
protected ?bool $isPayloadEncoded = null;
|
||||
|
||||
public function __construct(
|
||||
private readonly AlgorithmManager $signatureAlgorithmManager
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the algorithm manager associated to the builder.
|
||||
*/
|
||||
public function getSignatureAlgorithmManager(): AlgorithmManager
|
||||
{
|
||||
return $this->signatureAlgorithmManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the current data.
|
||||
*/
|
||||
public function create(): self
|
||||
{
|
||||
$this->payload = null;
|
||||
$this->isPayloadDetached = false;
|
||||
$this->signatures = [];
|
||||
$this->isPayloadEncoded = null;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the payload. This method will return a new JWSBuilder object.
|
||||
*/
|
||||
public function withPayload(string $payload, bool $isPayloadDetached = false): self
|
||||
{
|
||||
if (mb_detect_encoding($payload, 'UTF-8', true) === false) {
|
||||
throw new InvalidArgumentException('The payload must be encoded in UTF-8');
|
||||
}
|
||||
$clone = clone $this;
|
||||
$clone->payload = $payload;
|
||||
$clone->isPayloadDetached = $isPayloadDetached;
|
||||
|
||||
return $clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the information needed to compute the signature. This method will return a new JWSBuilder object.
|
||||
*
|
||||
* @param array{alg?: string, string?: mixed} $protectedHeader
|
||||
* @param array{alg?: string, string?: mixed} $header
|
||||
*/
|
||||
public function addSignature(JWK $signatureKey, array $protectedHeader, array $header = []): self
|
||||
{
|
||||
$this->checkB64AndCriticalHeader($protectedHeader);
|
||||
$isPayloadEncoded = $this->checkIfPayloadIsEncoded($protectedHeader);
|
||||
if ($this->isPayloadEncoded === null) {
|
||||
$this->isPayloadEncoded = $isPayloadEncoded;
|
||||
} elseif ($this->isPayloadEncoded !== $isPayloadEncoded) {
|
||||
throw new InvalidArgumentException('Foreign payload encoding detected.');
|
||||
}
|
||||
$this->checkDuplicatedHeaderParameters($protectedHeader, $header);
|
||||
KeyChecker::checkKeyUsage($signatureKey, 'signature');
|
||||
$algorithm = $this->findSignatureAlgorithm($signatureKey, $protectedHeader, $header);
|
||||
KeyChecker::checkKeyAlgorithm($signatureKey, $algorithm->name());
|
||||
$clone = clone $this;
|
||||
$clone->signatures[] = [
|
||||
'signature_algorithm' => $algorithm,
|
||||
'signature_key' => $signatureKey,
|
||||
'protected_header' => $protectedHeader,
|
||||
'header' => $header,
|
||||
];
|
||||
|
||||
return $clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes all signatures and return the expected JWS object.
|
||||
*/
|
||||
public function build(): JWS
|
||||
{
|
||||
if ($this->payload === null) {
|
||||
throw new RuntimeException('The payload is not set.');
|
||||
}
|
||||
if (count($this->signatures) === 0) {
|
||||
throw new RuntimeException('At least one signature must be set.');
|
||||
}
|
||||
|
||||
$encodedPayload = $this->isPayloadEncoded === false ? $this->payload : Base64UrlSafe::encodeUnpadded(
|
||||
$this->payload
|
||||
);
|
||||
$jws = new JWS($this->payload, $encodedPayload, $this->isPayloadDetached);
|
||||
foreach ($this->signatures as $signature) {
|
||||
/** @var MacAlgorithm|SignatureAlgorithm $algorithm */
|
||||
$algorithm = $signature['signature_algorithm'];
|
||||
/** @var JWK $signatureKey */
|
||||
$signatureKey = $signature['signature_key'];
|
||||
/** @var array<string, mixed> $protectedHeader */
|
||||
$protectedHeader = $signature['protected_header'];
|
||||
/** @var array<string, mixed> $header */
|
||||
$header = $signature['header'];
|
||||
$encodedProtectedHeader = count($protectedHeader) === 0 ? null : Base64UrlSafe::encodeUnpadded(
|
||||
JsonConverter::encode($protectedHeader)
|
||||
);
|
||||
$input = sprintf('%s.%s', $encodedProtectedHeader, $encodedPayload);
|
||||
if ($algorithm instanceof SignatureAlgorithm) {
|
||||
$s = $algorithm->sign($signatureKey, $input);
|
||||
} else {
|
||||
$s = $algorithm->hash($signatureKey, $input);
|
||||
}
|
||||
$jws = $jws->addSignature($s, $protectedHeader, $encodedProtectedHeader, $header);
|
||||
}
|
||||
|
||||
return $jws;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $protectedHeader
|
||||
*/
|
||||
private function checkIfPayloadIsEncoded(array $protectedHeader): bool
|
||||
{
|
||||
return ! array_key_exists('b64', $protectedHeader) || $protectedHeader['b64'] === true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $protectedHeader
|
||||
*/
|
||||
private function checkB64AndCriticalHeader(array $protectedHeader): void
|
||||
{
|
||||
if (! array_key_exists('b64', $protectedHeader)) {
|
||||
return;
|
||||
}
|
||||
if (! array_key_exists('crit', $protectedHeader)) {
|
||||
throw new LogicException(
|
||||
'The protected header parameter "crit" is mandatory when protected header parameter "b64" is set.'
|
||||
);
|
||||
}
|
||||
if (! is_array($protectedHeader['crit'])) {
|
||||
throw new LogicException('The protected header parameter "crit" must be an array.');
|
||||
}
|
||||
if (! in_array('b64', $protectedHeader['crit'], true)) {
|
||||
throw new LogicException(
|
||||
'The protected header parameter "crit" must contain "b64" when protected header parameter "b64" is set.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array{alg?: string, string?: mixed} $protectedHeader
|
||||
* @param array{alg?: string, string?: mixed} $header
|
||||
* @return MacAlgorithm|SignatureAlgorithm
|
||||
*/
|
||||
private function findSignatureAlgorithm(JWK $key, array $protectedHeader, array $header): Algorithm
|
||||
{
|
||||
$completeHeader = [...$header, ...$protectedHeader];
|
||||
if (! array_key_exists('alg', $completeHeader)) {
|
||||
throw new InvalidArgumentException('No "alg" parameter set in the header.');
|
||||
}
|
||||
if ($key->has('alg') && $key->get('alg') !== $completeHeader['alg']) {
|
||||
throw new InvalidArgumentException(sprintf(
|
||||
'The algorithm "%s" is not allowed with this key.',
|
||||
$completeHeader['alg']
|
||||
));
|
||||
}
|
||||
|
||||
$algorithm = $this->signatureAlgorithmManager->get($completeHeader['alg']);
|
||||
if (! $algorithm instanceof SignatureAlgorithm && ! $algorithm instanceof MacAlgorithm) {
|
||||
throw new InvalidArgumentException(sprintf('The algorithm "%s" is not supported.', $completeHeader['alg']));
|
||||
}
|
||||
|
||||
return $algorithm;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $header1
|
||||
* @param array<string, mixed> $header2
|
||||
*/
|
||||
private function checkDuplicatedHeaderParameters(array $header1, array $header2): void
|
||||
{
|
||||
$inter = array_intersect_key($header1, $header2);
|
||||
if (count($inter) !== 0) {
|
||||
throw new InvalidArgumentException(sprintf(
|
||||
'The header contains duplicated entries: %s.',
|
||||
implode(', ', array_keys($inter))
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
27
libraries/vendor/web-token/jwt-signature/JWSBuilderFactory.php
vendored
Normal file
27
libraries/vendor/web-token/jwt-signature/JWSBuilderFactory.php
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Jose\Component\Signature;
|
||||
|
||||
use Jose\Component\Core\AlgorithmManagerFactory;
|
||||
|
||||
class JWSBuilderFactory
|
||||
{
|
||||
public function __construct(
|
||||
private readonly AlgorithmManagerFactory $signatureAlgorithmManagerFactory
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* This method creates a JWSBuilder using the given algorithm aliases.
|
||||
*
|
||||
* @param string[] $algorithms
|
||||
*/
|
||||
public function create(array $algorithms): JWSBuilder
|
||||
{
|
||||
$algorithmManager = $this->signatureAlgorithmManagerFactory->create($algorithms);
|
||||
|
||||
return new JWSBuilder($algorithmManager);
|
||||
}
|
||||
}
|
||||
97
libraries/vendor/web-token/jwt-signature/JWSLoader.php
vendored
Normal file
97
libraries/vendor/web-token/jwt-signature/JWSLoader.php
vendored
Normal file
@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Jose\Component\Signature;
|
||||
|
||||
use Exception;
|
||||
use Jose\Component\Checker\HeaderCheckerManager;
|
||||
use Jose\Component\Core\JWK;
|
||||
use Jose\Component\Core\JWKSet;
|
||||
use Jose\Component\Signature\Serializer\JWSSerializerManager;
|
||||
use Throwable;
|
||||
|
||||
class JWSLoader
|
||||
{
|
||||
public function __construct(
|
||||
private readonly JWSSerializerManager $serializerManager,
|
||||
private readonly JWSVerifier $jwsVerifier,
|
||||
private readonly ?HeaderCheckerManager $headerCheckerManager
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the JWSVerifier associated to the JWSLoader.
|
||||
*/
|
||||
public function getJwsVerifier(): JWSVerifier
|
||||
{
|
||||
return $this->jwsVerifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Header Checker Manager associated to the JWSLoader.
|
||||
*/
|
||||
public function getHeaderCheckerManager(): ?HeaderCheckerManager
|
||||
{
|
||||
return $this->headerCheckerManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the JWSSerializer associated to the JWSLoader.
|
||||
*/
|
||||
public function getSerializerManager(): JWSSerializerManager
|
||||
{
|
||||
return $this->serializerManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will try to load and verify the token using the given key. It returns a JWS and will populate the
|
||||
* $signature variable in case of success, otherwise an exception is thrown.
|
||||
*/
|
||||
public function loadAndVerifyWithKey(string $token, JWK $key, ?int &$signature, ?string $payload = null): JWS
|
||||
{
|
||||
$keyset = new JWKSet([$key]);
|
||||
|
||||
return $this->loadAndVerifyWithKeySet($token, $keyset, $signature, $payload);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will try to load and verify the token using the given key set. It returns a JWS and will populate the
|
||||
* $signature variable in case of success, otherwise an exception is thrown.
|
||||
*/
|
||||
public function loadAndVerifyWithKeySet(
|
||||
string $token,
|
||||
JWKSet $keyset,
|
||||
?int &$signature,
|
||||
?string $payload = null
|
||||
): JWS {
|
||||
try {
|
||||
$jws = $this->serializerManager->unserialize($token);
|
||||
$nbSignatures = $jws->countSignatures();
|
||||
for ($i = 0; $i < $nbSignatures; ++$i) {
|
||||
if ($this->processSignature($jws, $keyset, $i, $payload)) {
|
||||
$signature = $i;
|
||||
|
||||
return $jws;
|
||||
}
|
||||
}
|
||||
} catch (Throwable) {
|
||||
// Nothing to do. Exception thrown just after
|
||||
}
|
||||
|
||||
throw new Exception('Unable to load and verify the token.');
|
||||
}
|
||||
|
||||
private function processSignature(JWS $jws, JWKSet $keyset, int $signature, ?string $payload): bool
|
||||
{
|
||||
try {
|
||||
if ($this->headerCheckerManager !== null) {
|
||||
$this->headerCheckerManager->check($jws, $signature);
|
||||
}
|
||||
|
||||
return $this->jwsVerifier->verifyWithKeySet($jws, $keyset, $signature, $payload);
|
||||
} catch (Throwable) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
40
libraries/vendor/web-token/jwt-signature/JWSLoaderFactory.php
vendored
Normal file
40
libraries/vendor/web-token/jwt-signature/JWSLoaderFactory.php
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Jose\Component\Signature;
|
||||
|
||||
use Jose\Component\Checker\HeaderCheckerManagerFactory;
|
||||
use Jose\Component\Signature\Serializer\JWSSerializerManagerFactory;
|
||||
|
||||
class JWSLoaderFactory
|
||||
{
|
||||
public function __construct(
|
||||
private readonly JWSSerializerManagerFactory $jwsSerializerManagerFactory,
|
||||
private readonly JWSVerifierFactory $jwsVerifierFactory,
|
||||
private readonly ?HeaderCheckerManagerFactory $headerCheckerManagerFactory
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a JWSLoader using the given serializer aliases, signature algorithm aliases and (optionally) the header
|
||||
* checker aliases.
|
||||
*/
|
||||
/**
|
||||
* @param array<string> $serializers
|
||||
* @param array<string> $algorithms
|
||||
* @param array<string> $headerCheckers
|
||||
*/
|
||||
public function create(array $serializers, array $algorithms, array $headerCheckers = []): JWSLoader
|
||||
{
|
||||
$serializerManager = $this->jwsSerializerManagerFactory->create($serializers);
|
||||
$jwsVerifier = $this->jwsVerifierFactory->create($algorithms);
|
||||
if ($this->headerCheckerManagerFactory !== null) {
|
||||
$headerCheckerManager = $this->headerCheckerManagerFactory->create($headerCheckers);
|
||||
} else {
|
||||
$headerCheckerManager = null;
|
||||
}
|
||||
|
||||
return new JWSLoader($serializerManager, $jwsVerifier, $headerCheckerManager);
|
||||
}
|
||||
}
|
||||
36
libraries/vendor/web-token/jwt-signature/JWSTokenSupport.php
vendored
Normal file
36
libraries/vendor/web-token/jwt-signature/JWSTokenSupport.php
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Jose\Component\Signature;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use Jose\Component\Checker\TokenTypeSupport;
|
||||
use Jose\Component\Core\JWT;
|
||||
|
||||
final class JWSTokenSupport implements TokenTypeSupport
|
||||
{
|
||||
public function supports(JWT $jwt): bool
|
||||
{
|
||||
return $jwt instanceof JWS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $protectedHeader
|
||||
* @param array<string, mixed> $unprotectedHeader
|
||||
*/
|
||||
public function retrieveTokenHeaders(JWT $jwt, int $index, array &$protectedHeader, array &$unprotectedHeader): void
|
||||
{
|
||||
if (! $jwt instanceof JWS) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($index > $jwt->countSignatures()) {
|
||||
throw new InvalidArgumentException('Unknown signature index.');
|
||||
}
|
||||
$protectedHeader = $jwt->getSignature($index)
|
||||
->getProtectedHeader();
|
||||
$unprotectedHeader = $jwt->getSignature($index)
|
||||
->getHeader();
|
||||
}
|
||||
}
|
||||
163
libraries/vendor/web-token/jwt-signature/JWSVerifier.php
vendored
Normal file
163
libraries/vendor/web-token/jwt-signature/JWSVerifier.php
vendored
Normal file
@ -0,0 +1,163 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Jose\Component\Signature;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use Jose\Component\Core\Algorithm;
|
||||
use Jose\Component\Core\AlgorithmManager;
|
||||
use Jose\Component\Core\JWK;
|
||||
use Jose\Component\Core\JWKSet;
|
||||
use Jose\Component\Core\Util\KeyChecker;
|
||||
use Jose\Component\Signature\Algorithm\MacAlgorithm;
|
||||
use Jose\Component\Signature\Algorithm\SignatureAlgorithm;
|
||||
use ParagonIE\ConstantTime\Base64UrlSafe;
|
||||
use Throwable;
|
||||
|
||||
class JWSVerifier
|
||||
{
|
||||
public function __construct(
|
||||
private readonly AlgorithmManager $signatureAlgorithmManager
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the algorithm manager associated to the JWSVerifier.
|
||||
*/
|
||||
public function getSignatureAlgorithmManager(): AlgorithmManager
|
||||
{
|
||||
return $this->signatureAlgorithmManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will try to verify the JWS object using the given key and for the given signature. It returns true if
|
||||
* the signature is verified, otherwise false.
|
||||
*
|
||||
* @return bool true if the verification of the signature succeeded, else false
|
||||
*/
|
||||
public function verifyWithKey(JWS $jws, JWK $jwk, int $signature, ?string $detachedPayload = null): bool
|
||||
{
|
||||
$jwkset = new JWKSet([$jwk]);
|
||||
|
||||
return $this->verifyWithKeySet($jws, $jwkset, $signature, $detachedPayload);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will try to verify the JWS object using the given key set and for the given signature. It returns
|
||||
* true if the signature is verified, otherwise false.
|
||||
*
|
||||
* @param JWS $jws A JWS object
|
||||
* @param JWKSet $jwkset The signature will be verified using keys in the key set
|
||||
* @param JWK $jwk The key used to verify the signature in case of success
|
||||
* @param string|null $detachedPayload If not null, the value must be the detached payload encoded in Base64 URL safe. If the input contains a payload, throws an exception.
|
||||
*
|
||||
* @return bool true if the verification of the signature succeeded, else false
|
||||
*/
|
||||
public function verifyWithKeySet(
|
||||
JWS $jws,
|
||||
JWKSet $jwkset,
|
||||
int $signatureIndex,
|
||||
?string $detachedPayload = null,
|
||||
JWK &$jwk = null
|
||||
): bool {
|
||||
if ($jwkset->count() === 0) {
|
||||
throw new InvalidArgumentException('There is no key in the key set.');
|
||||
}
|
||||
if ($jws->countSignatures() === 0) {
|
||||
throw new InvalidArgumentException('The JWS does not contain any signature.');
|
||||
}
|
||||
$this->checkPayload($jws, $detachedPayload);
|
||||
$signature = $jws->getSignature($signatureIndex);
|
||||
|
||||
return $this->verifySignature($jws, $jwkset, $signature, $detachedPayload, $jwk);
|
||||
}
|
||||
|
||||
private function verifySignature(
|
||||
JWS $jws,
|
||||
JWKSet $jwkset,
|
||||
Signature $signature,
|
||||
?string $detachedPayload = null,
|
||||
JWK &$successJwk = null
|
||||
): bool {
|
||||
$input = $this->getInputToVerify($jws, $signature, $detachedPayload);
|
||||
$algorithm = $this->getAlgorithm($signature);
|
||||
foreach ($jwkset->all() as $jwk) {
|
||||
try {
|
||||
KeyChecker::checkKeyUsage($jwk, 'verification');
|
||||
KeyChecker::checkKeyAlgorithm($jwk, $algorithm->name());
|
||||
if ($algorithm->verify($jwk, $input, $signature->getSignature()) === true) {
|
||||
$successJwk = $jwk;
|
||||
|
||||
return true;
|
||||
}
|
||||
} catch (Throwable) {
|
||||
//We do nothing, we continue with other keys
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function getInputToVerify(JWS $jws, Signature $signature, ?string $detachedPayload): string
|
||||
{
|
||||
$payload = $jws->getPayload();
|
||||
$isPayloadEmpty = $payload === null || $payload === '';
|
||||
$encodedProtectedHeader = $signature->getEncodedProtectedHeader() ?? '';
|
||||
$isPayloadBase64Encoded = ! $signature->hasProtectedHeaderParameter(
|
||||
'b64'
|
||||
) || $signature->getProtectedHeaderParameter('b64') === true;
|
||||
$encodedPayload = $jws->getEncodedPayload();
|
||||
|
||||
if ($isPayloadBase64Encoded && $encodedPayload !== null) {
|
||||
return sprintf('%s.%s', $encodedProtectedHeader, $encodedPayload);
|
||||
}
|
||||
|
||||
$callable = $isPayloadBase64Encoded === true ? static fn (?string $p): string => Base64UrlSafe::encodeUnpadded(
|
||||
$p ?? ''
|
||||
)
|
||||
: static fn (?string $p): string => $p ?? '';
|
||||
|
||||
$payloadToUse = $callable($isPayloadEmpty ? $detachedPayload : $payload);
|
||||
|
||||
return sprintf('%s.%s', $encodedProtectedHeader, $payloadToUse);
|
||||
}
|
||||
|
||||
private function checkPayload(JWS $jws, ?string $detachedPayload = null): void
|
||||
{
|
||||
$isPayloadEmpty = $this->isPayloadEmpty($jws->getPayload());
|
||||
if ($detachedPayload !== null && ! $isPayloadEmpty) {
|
||||
throw new InvalidArgumentException('A detached payload is set, but the JWS already has a payload.');
|
||||
}
|
||||
if ($isPayloadEmpty && $detachedPayload === null) {
|
||||
throw new InvalidArgumentException('The JWS has a detached payload, but no payload is provided.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return MacAlgorithm|SignatureAlgorithm
|
||||
*/
|
||||
private function getAlgorithm(Signature $signature): Algorithm
|
||||
{
|
||||
$completeHeader = [...$signature->getProtectedHeader(), ...$signature->getHeader()];
|
||||
if (! isset($completeHeader['alg'])) {
|
||||
throw new InvalidArgumentException('No "alg" parameter set in the header.');
|
||||
}
|
||||
|
||||
$algorithm = $this->signatureAlgorithmManager->get($completeHeader['alg']);
|
||||
if (! $algorithm instanceof SignatureAlgorithm && ! $algorithm instanceof MacAlgorithm) {
|
||||
throw new InvalidArgumentException(sprintf(
|
||||
'The algorithm "%s" is not supported or is not a signature or MAC algorithm.',
|
||||
$completeHeader['alg']
|
||||
));
|
||||
}
|
||||
|
||||
return $algorithm;
|
||||
}
|
||||
|
||||
private function isPayloadEmpty(?string $payload): bool
|
||||
{
|
||||
return $payload === null || $payload === '';
|
||||
}
|
||||
}
|
||||
27
libraries/vendor/web-token/jwt-signature/JWSVerifierFactory.php
vendored
Normal file
27
libraries/vendor/web-token/jwt-signature/JWSVerifierFactory.php
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Jose\Component\Signature;
|
||||
|
||||
use Jose\Component\Core\AlgorithmManagerFactory;
|
||||
|
||||
class JWSVerifierFactory
|
||||
{
|
||||
public function __construct(
|
||||
private readonly AlgorithmManagerFactory $algorithmManagerFactory
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a JWSVerifier using the given signature algorithm aliases.
|
||||
*
|
||||
* @param string[] $algorithms
|
||||
*/
|
||||
public function create(array $algorithms): JWSVerifier
|
||||
{
|
||||
$algorithmManager = $this->algorithmManagerFactory->create($algorithms);
|
||||
|
||||
return new JWSVerifier($algorithmManager);
|
||||
}
|
||||
}
|
||||
21
libraries/vendor/web-token/jwt-signature/LICENSE
vendored
Normal file
21
libraries/vendor/web-token/jwt-signature/LICENSE
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014-2019 Spomky-Labs
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
88
libraries/vendor/web-token/jwt-signature/Serializer/CompactSerializer.php
vendored
Normal file
88
libraries/vendor/web-token/jwt-signature/Serializer/CompactSerializer.php
vendored
Normal file
@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Jose\Component\Signature\Serializer;
|
||||
|
||||
use function count;
|
||||
use InvalidArgumentException;
|
||||
use function is_array;
|
||||
use Jose\Component\Core\Util\JsonConverter;
|
||||
use Jose\Component\Signature\JWS;
|
||||
use LogicException;
|
||||
use ParagonIE\ConstantTime\Base64UrlSafe;
|
||||
use Throwable;
|
||||
|
||||
final class CompactSerializer extends Serializer
|
||||
{
|
||||
public const NAME = 'jws_compact';
|
||||
|
||||
public function displayName(): string
|
||||
{
|
||||
return 'JWS Compact';
|
||||
}
|
||||
|
||||
public function name(): string
|
||||
{
|
||||
return self::NAME;
|
||||
}
|
||||
|
||||
public function serialize(JWS $jws, ?int $signatureIndex = null): string
|
||||
{
|
||||
if ($signatureIndex === null) {
|
||||
$signatureIndex = 0;
|
||||
}
|
||||
$signature = $jws->getSignature($signatureIndex);
|
||||
if (count($signature->getHeader()) !== 0) {
|
||||
throw new LogicException(
|
||||
'The signature contains unprotected header parameters and cannot be converted into compact JSON.'
|
||||
);
|
||||
}
|
||||
$isEmptyPayload = $jws->getEncodedPayload() === null || $jws->getEncodedPayload() === '';
|
||||
if (! $isEmptyPayload && ! $this->isPayloadEncoded($signature->getProtectedHeader())) {
|
||||
if (preg_match('/^[\x{20}-\x{2d}|\x{2f}-\x{7e}]*$/u', $jws->getPayload() ?? '') !== 1) {
|
||||
throw new LogicException('Unable to convert the JWS with non-encoded payload.');
|
||||
}
|
||||
}
|
||||
|
||||
return sprintf(
|
||||
'%s.%s.%s',
|
||||
$signature->getEncodedProtectedHeader(),
|
||||
$jws->getEncodedPayload(),
|
||||
Base64UrlSafe::encodeUnpadded($signature->getSignature())
|
||||
);
|
||||
}
|
||||
|
||||
public function unserialize(string $input): JWS
|
||||
{
|
||||
$parts = explode('.', $input);
|
||||
if (count($parts) !== 3) {
|
||||
throw new InvalidArgumentException('Unsupported input');
|
||||
}
|
||||
|
||||
try {
|
||||
$encodedProtectedHeader = $parts[0];
|
||||
$protectedHeader = JsonConverter::decode(Base64UrlSafe::decode($parts[0]));
|
||||
if (! is_array($protectedHeader)) {
|
||||
throw new InvalidArgumentException('Bad protected header.');
|
||||
}
|
||||
$hasPayload = $parts[1] !== '';
|
||||
if (! $hasPayload) {
|
||||
$payload = null;
|
||||
$encodedPayload = null;
|
||||
} else {
|
||||
$encodedPayload = $parts[1];
|
||||
$payload = $this->isPayloadEncoded($protectedHeader) ? Base64UrlSafe::decode(
|
||||
$encodedPayload
|
||||
) : $encodedPayload;
|
||||
}
|
||||
$signature = Base64UrlSafe::decode($parts[2]);
|
||||
|
||||
$jws = new JWS($payload, $encodedPayload, ! $hasPayload);
|
||||
|
||||
return $jws->addSignature($signature, $protectedHeader, $encodedProtectedHeader);
|
||||
} catch (Throwable $throwable) {
|
||||
throw new InvalidArgumentException('Unsupported input', $throwable->getCode(), $throwable);
|
||||
}
|
||||
}
|
||||
}
|
||||
97
libraries/vendor/web-token/jwt-signature/Serializer/JSONFlattenedSerializer.php
vendored
Normal file
97
libraries/vendor/web-token/jwt-signature/Serializer/JSONFlattenedSerializer.php
vendored
Normal file
@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Jose\Component\Signature\Serializer;
|
||||
|
||||
use function count;
|
||||
use InvalidArgumentException;
|
||||
use function is_array;
|
||||
use Jose\Component\Core\Util\JsonConverter;
|
||||
use Jose\Component\Signature\JWS;
|
||||
use ParagonIE\ConstantTime\Base64UrlSafe;
|
||||
|
||||
final class JSONFlattenedSerializer extends Serializer
|
||||
{
|
||||
public const NAME = 'jws_json_flattened';
|
||||
|
||||
public function displayName(): string
|
||||
{
|
||||
return 'JWS JSON Flattened';
|
||||
}
|
||||
|
||||
public function name(): string
|
||||
{
|
||||
return self::NAME;
|
||||
}
|
||||
|
||||
public function serialize(JWS $jws, ?int $signatureIndex = null): string
|
||||
{
|
||||
if ($signatureIndex === null) {
|
||||
$signatureIndex = 0;
|
||||
}
|
||||
$signature = $jws->getSignature($signatureIndex);
|
||||
|
||||
$data = [];
|
||||
$encodedPayload = $jws->getEncodedPayload();
|
||||
if ($encodedPayload !== null && $encodedPayload !== '') {
|
||||
$data['payload'] = $encodedPayload;
|
||||
}
|
||||
$encodedProtectedHeader = $signature->getEncodedProtectedHeader();
|
||||
if ($encodedProtectedHeader !== null && $encodedProtectedHeader !== '') {
|
||||
$data['protected'] = $encodedProtectedHeader;
|
||||
}
|
||||
$header = $signature->getHeader();
|
||||
if (count($header) !== 0) {
|
||||
$data['header'] = $header;
|
||||
}
|
||||
$data['signature'] = Base64UrlSafe::encodeUnpadded($signature->getSignature());
|
||||
|
||||
return JsonConverter::encode($data);
|
||||
}
|
||||
|
||||
public function unserialize(string $input): JWS
|
||||
{
|
||||
$data = JsonConverter::decode($input);
|
||||
if (! is_array($data)) {
|
||||
throw new InvalidArgumentException('Unsupported input.');
|
||||
}
|
||||
if (! isset($data['signature'])) {
|
||||
throw new InvalidArgumentException('Unsupported input.');
|
||||
}
|
||||
$signature = Base64UrlSafe::decode($data['signature']);
|
||||
|
||||
if (isset($data['protected'])) {
|
||||
$encodedProtectedHeader = $data['protected'];
|
||||
$protectedHeader = JsonConverter::decode(Base64UrlSafe::decode($data['protected']));
|
||||
if (! is_array($protectedHeader)) {
|
||||
throw new InvalidArgumentException('Bad protected header.');
|
||||
}
|
||||
} else {
|
||||
$encodedProtectedHeader = null;
|
||||
$protectedHeader = [];
|
||||
}
|
||||
if (isset($data['header'])) {
|
||||
if (! is_array($data['header'])) {
|
||||
throw new InvalidArgumentException('Bad header.');
|
||||
}
|
||||
$header = $data['header'];
|
||||
} else {
|
||||
$header = [];
|
||||
}
|
||||
|
||||
if (isset($data['payload'])) {
|
||||
$encodedPayload = $data['payload'];
|
||||
$payload = $this->isPayloadEncoded($protectedHeader) ? Base64UrlSafe::decode(
|
||||
$encodedPayload
|
||||
) : $encodedPayload;
|
||||
} else {
|
||||
$payload = null;
|
||||
$encodedPayload = null;
|
||||
}
|
||||
|
||||
$jws = new JWS($payload, $encodedPayload, $encodedPayload === null);
|
||||
|
||||
return $jws->addSignature($signature, $protectedHeader, $encodedProtectedHeader, $header);
|
||||
}
|
||||
}
|
||||
160
libraries/vendor/web-token/jwt-signature/Serializer/JSONGeneralSerializer.php
vendored
Normal file
160
libraries/vendor/web-token/jwt-signature/Serializer/JSONGeneralSerializer.php
vendored
Normal file
@ -0,0 +1,160 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Jose\Component\Signature\Serializer;
|
||||
|
||||
use function array_key_exists;
|
||||
use function count;
|
||||
use InvalidArgumentException;
|
||||
use function is_array;
|
||||
use function is_string;
|
||||
use Jose\Component\Core\Util\JsonConverter;
|
||||
use Jose\Component\Signature\JWS;
|
||||
use LogicException;
|
||||
use ParagonIE\ConstantTime\Base64UrlSafe;
|
||||
|
||||
final class JSONGeneralSerializer extends Serializer
|
||||
{
|
||||
public const NAME = 'jws_json_general';
|
||||
|
||||
public function displayName(): string
|
||||
{
|
||||
return 'JWS JSON General';
|
||||
}
|
||||
|
||||
public function name(): string
|
||||
{
|
||||
return self::NAME;
|
||||
}
|
||||
|
||||
public function serialize(JWS $jws, ?int $signatureIndex = null): string
|
||||
{
|
||||
if ($jws->countSignatures() === 0) {
|
||||
throw new LogicException('No signature.');
|
||||
}
|
||||
|
||||
$data = [];
|
||||
$this->checkPayloadEncoding($jws);
|
||||
|
||||
if ($jws->isPayloadDetached() === false) {
|
||||
$data['payload'] = $jws->getEncodedPayload();
|
||||
}
|
||||
|
||||
$data['signatures'] = [];
|
||||
foreach ($jws->getSignatures() as $signature) {
|
||||
$tmp = [
|
||||
'signature' => Base64UrlSafe::encodeUnpadded($signature->getSignature()),
|
||||
];
|
||||
$values = [
|
||||
'protected' => $signature->getEncodedProtectedHeader(),
|
||||
'header' => $signature->getHeader(),
|
||||
];
|
||||
|
||||
foreach ($values as $key => $value) {
|
||||
if ((is_string($value) && $value !== '') || (is_array($value) && count($value) !== 0)) {
|
||||
$tmp[$key] = $value;
|
||||
}
|
||||
}
|
||||
$data['signatures'][] = $tmp;
|
||||
}
|
||||
|
||||
return JsonConverter::encode($data);
|
||||
}
|
||||
|
||||
public function unserialize(string $input): JWS
|
||||
{
|
||||
$data = JsonConverter::decode($input);
|
||||
if (! is_array($data)) {
|
||||
throw new InvalidArgumentException('Unsupported input.');
|
||||
}
|
||||
if (! isset($data['signatures'])) {
|
||||
throw new InvalidArgumentException('Unsupported input.');
|
||||
}
|
||||
|
||||
$isPayloadEncoded = null;
|
||||
$rawPayload = $data['payload'] ?? null;
|
||||
$signatures = [];
|
||||
foreach ($data['signatures'] as $signature) {
|
||||
if (! isset($signature['signature'])) {
|
||||
throw new InvalidArgumentException('Unsupported input.');
|
||||
}
|
||||
[$encodedProtectedHeader, $protectedHeader, $header] = $this->processHeaders($signature);
|
||||
$signatures[] = [
|
||||
'signature' => Base64UrlSafe::decode($signature['signature']),
|
||||
'protected' => $protectedHeader,
|
||||
'encoded_protected' => $encodedProtectedHeader,
|
||||
'header' => $header,
|
||||
];
|
||||
$isPayloadEncoded = $this->processIsPayloadEncoded($isPayloadEncoded, $protectedHeader);
|
||||
}
|
||||
|
||||
$payload = $this->processPayload($rawPayload, $isPayloadEncoded);
|
||||
$jws = new JWS($payload, $rawPayload);
|
||||
foreach ($signatures as $signature) {
|
||||
$jws = $jws->addSignature(
|
||||
$signature['signature'],
|
||||
$signature['protected'],
|
||||
$signature['encoded_protected'],
|
||||
$signature['header']
|
||||
);
|
||||
}
|
||||
|
||||
return $jws;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $protectedHeader
|
||||
*/
|
||||
private function processIsPayloadEncoded(?bool $isPayloadEncoded, array $protectedHeader): bool
|
||||
{
|
||||
if ($isPayloadEncoded === null) {
|
||||
return $this->isPayloadEncoded($protectedHeader);
|
||||
}
|
||||
if ($this->isPayloadEncoded($protectedHeader) !== $isPayloadEncoded) {
|
||||
throw new InvalidArgumentException('Foreign payload encoding detected.');
|
||||
}
|
||||
|
||||
return $isPayloadEncoded;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array{protected?: string, header?: array<string, mixed>} $signature
|
||||
* @return array<mixed>
|
||||
*/
|
||||
private function processHeaders(array $signature): array
|
||||
{
|
||||
$encodedProtectedHeader = $signature['protected'] ?? null;
|
||||
$protectedHeader = $encodedProtectedHeader === null ? [] : JsonConverter::decode(
|
||||
Base64UrlSafe::decode($encodedProtectedHeader)
|
||||
);
|
||||
$header = array_key_exists('header', $signature) ? $signature['header'] : [];
|
||||
|
||||
return [$encodedProtectedHeader, $protectedHeader, $header];
|
||||
}
|
||||
|
||||
private function processPayload(?string $rawPayload, ?bool $isPayloadEncoded): ?string
|
||||
{
|
||||
if ($rawPayload === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $isPayloadEncoded === false ? $rawPayload : Base64UrlSafe::decode($rawPayload);
|
||||
}
|
||||
|
||||
private function checkPayloadEncoding(JWS $jws): void
|
||||
{
|
||||
if ($jws->isPayloadDetached()) {
|
||||
return;
|
||||
}
|
||||
$is_encoded = null;
|
||||
foreach ($jws->getSignatures() as $signature) {
|
||||
if ($is_encoded === null) {
|
||||
$is_encoded = $this->isPayloadEncoded($signature->getProtectedHeader());
|
||||
}
|
||||
if ($is_encoded !== $this->isPayloadEncoded($signature->getProtectedHeader())) {
|
||||
throw new LogicException('Foreign payload encoding detected.');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
29
libraries/vendor/web-token/jwt-signature/Serializer/JWSSerializer.php
vendored
Normal file
29
libraries/vendor/web-token/jwt-signature/Serializer/JWSSerializer.php
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Jose\Component\Signature\Serializer;
|
||||
|
||||
use Jose\Component\Signature\JWS;
|
||||
|
||||
interface JWSSerializer
|
||||
{
|
||||
/**
|
||||
* The name of the serialization.
|
||||
*/
|
||||
public function name(): string;
|
||||
|
||||
public function displayName(): string;
|
||||
|
||||
/**
|
||||
* Converts a JWS into a string.
|
||||
*/
|
||||
public function serialize(JWS $jws, ?int $signatureIndex = null): string;
|
||||
|
||||
/**
|
||||
* Loads data and return a JWS object.
|
||||
*
|
||||
* @param string $input A string that represents a JWS
|
||||
*/
|
||||
public function unserialize(string $input): JWS;
|
||||
}
|
||||
73
libraries/vendor/web-token/jwt-signature/Serializer/JWSSerializerManager.php
vendored
Normal file
73
libraries/vendor/web-token/jwt-signature/Serializer/JWSSerializerManager.php
vendored
Normal file
@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Jose\Component\Signature\Serializer;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use Jose\Component\Signature\JWS;
|
||||
|
||||
class JWSSerializerManager
|
||||
{
|
||||
/**
|
||||
* @var JWSSerializer[]
|
||||
*/
|
||||
private array $serializers = [];
|
||||
|
||||
/**
|
||||
* @param JWSSerializer[] $serializers
|
||||
*/
|
||||
public function __construct(array $serializers)
|
||||
{
|
||||
foreach ($serializers as $serializer) {
|
||||
$this->add($serializer);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function list(): array
|
||||
{
|
||||
return array_keys($this->serializers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a JWS into a string.
|
||||
*/
|
||||
public function serialize(string $name, JWS $jws, ?int $signatureIndex = null): string
|
||||
{
|
||||
if (! isset($this->serializers[$name])) {
|
||||
throw new InvalidArgumentException(sprintf('Unsupported serializer "%s".', $name));
|
||||
}
|
||||
|
||||
return $this->serializers[$name]->serialize($jws, $signatureIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads data and return a JWS object.
|
||||
*
|
||||
* @param string $input A string that represents a JWS
|
||||
* @param string|null $name the name of the serializer if the input is unserialized
|
||||
*/
|
||||
public function unserialize(string $input, ?string &$name = null): JWS
|
||||
{
|
||||
foreach ($this->serializers as $serializer) {
|
||||
try {
|
||||
$jws = $serializer->unserialize($input);
|
||||
$name = $serializer->name();
|
||||
|
||||
return $jws;
|
||||
} catch (InvalidArgumentException) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException('Unsupported input.');
|
||||
}
|
||||
|
||||
private function add(JWSSerializer $serializer): void
|
||||
{
|
||||
$this->serializers[$serializer->name()] = $serializer;
|
||||
}
|
||||
}
|
||||
52
libraries/vendor/web-token/jwt-signature/Serializer/JWSSerializerManagerFactory.php
vendored
Normal file
52
libraries/vendor/web-token/jwt-signature/Serializer/JWSSerializerManagerFactory.php
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Jose\Component\Signature\Serializer;
|
||||
|
||||
use InvalidArgumentException;
|
||||
|
||||
class JWSSerializerManagerFactory
|
||||
{
|
||||
/**
|
||||
* @var JWSSerializer[]
|
||||
*/
|
||||
private array $serializers = [];
|
||||
|
||||
/**
|
||||
* @param string[] $names
|
||||
*/
|
||||
public function create(array $names): JWSSerializerManager
|
||||
{
|
||||
$serializers = [];
|
||||
foreach ($names as $name) {
|
||||
if (! isset($this->serializers[$name])) {
|
||||
throw new InvalidArgumentException(sprintf('Unsupported serializer "%s".', $name));
|
||||
}
|
||||
$serializers[] = $this->serializers[$name];
|
||||
}
|
||||
|
||||
return new JWSSerializerManager($serializers);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function names(): array
|
||||
{
|
||||
return array_keys($this->serializers);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return JWSSerializer[]
|
||||
*/
|
||||
public function all(): array
|
||||
{
|
||||
return $this->serializers;
|
||||
}
|
||||
|
||||
public function add(JWSSerializer $serializer): void
|
||||
{
|
||||
$this->serializers[$serializer->name()] = $serializer;
|
||||
}
|
||||
}
|
||||
18
libraries/vendor/web-token/jwt-signature/Serializer/Serializer.php
vendored
Normal file
18
libraries/vendor/web-token/jwt-signature/Serializer/Serializer.php
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Jose\Component\Signature\Serializer;
|
||||
|
||||
use function array_key_exists;
|
||||
|
||||
abstract class Serializer implements JWSSerializer
|
||||
{
|
||||
/**
|
||||
* @param array<string, mixed> $protectedHeader
|
||||
*/
|
||||
protected function isPayloadEncoded(array $protectedHeader): bool
|
||||
{
|
||||
return ! array_key_exists('b64', $protectedHeader) || $protectedHeader['b64'] === true;
|
||||
}
|
||||
}
|
||||
120
libraries/vendor/web-token/jwt-signature/Signature.php
vendored
Normal file
120
libraries/vendor/web-token/jwt-signature/Signature.php
vendored
Normal file
@ -0,0 +1,120 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Jose\Component\Signature;
|
||||
|
||||
use function array_key_exists;
|
||||
use InvalidArgumentException;
|
||||
|
||||
class Signature
|
||||
{
|
||||
private readonly ?string $encodedProtectedHeader;
|
||||
|
||||
/**
|
||||
* @var array<string, mixed>
|
||||
*/
|
||||
private readonly array $protectedHeader;
|
||||
|
||||
/**
|
||||
* @param array{alg?: string, string?: mixed} $protectedHeader
|
||||
* @param array{alg?: string, string?: mixed} $header
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly string $signature,
|
||||
array $protectedHeader,
|
||||
?string $encodedProtectedHeader,
|
||||
private readonly array $header
|
||||
) {
|
||||
$this->protectedHeader = $encodedProtectedHeader === null ? [] : $protectedHeader;
|
||||
$this->encodedProtectedHeader = $encodedProtectedHeader;
|
||||
}
|
||||
|
||||
/**
|
||||
* The protected header associated with the signature.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function getProtectedHeader(): array
|
||||
{
|
||||
return $this->protectedHeader;
|
||||
}
|
||||
|
||||
/**
|
||||
* The unprotected header associated with the signature.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function getHeader(): array
|
||||
{
|
||||
return $this->header;
|
||||
}
|
||||
|
||||
/**
|
||||
* The protected header associated with the signature.
|
||||
*/
|
||||
public function getEncodedProtectedHeader(): ?string
|
||||
{
|
||||
return $this->encodedProtectedHeader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the protected header of the specified key.
|
||||
*
|
||||
* @param string $key The key
|
||||
*
|
||||
* @return mixed|null Header value
|
||||
*/
|
||||
public function getProtectedHeaderParameter(string $key)
|
||||
{
|
||||
if ($this->hasProtectedHeaderParameter($key)) {
|
||||
return $this->getProtectedHeader()[$key];
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException(sprintf('The protected header "%s" does not exist', $key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the protected header has the given parameter.
|
||||
*
|
||||
* @param string $key The key
|
||||
*/
|
||||
public function hasProtectedHeaderParameter(string $key): bool
|
||||
{
|
||||
return array_key_exists($key, $this->getProtectedHeader());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the unprotected header of the specified key.
|
||||
*
|
||||
* @param string $key The key
|
||||
*
|
||||
* @return mixed|null Header value
|
||||
*/
|
||||
public function getHeaderParameter(string $key)
|
||||
{
|
||||
if (array_key_exists($key, $this->header)) {
|
||||
return $this->header[$key];
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException(sprintf('The header "%s" does not exist', $key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the unprotected header has the given parameter.
|
||||
*
|
||||
* @param string $key The key
|
||||
*/
|
||||
public function hasHeaderParameter(string $key): bool
|
||||
{
|
||||
return array_key_exists($key, $this->header);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the signature.
|
||||
*/
|
||||
public function getSignature(): string
|
||||
{
|
||||
return $this->signature;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user