Subiendo proyecto completo sin restricciones de git ignore
This commit is contained in:
77
vendor/lcobucci/jwt/src/Builder.php
vendored
Normal file
77
vendor/lcobucci/jwt/src/Builder.php
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT;
|
||||
|
||||
use DateTimeImmutable;
|
||||
use Lcobucci\JWT\Encoding\CannotEncodeContent;
|
||||
use Lcobucci\JWT\Signer\CannotSignPayload;
|
||||
use Lcobucci\JWT\Signer\Ecdsa\ConversionFailed;
|
||||
use Lcobucci\JWT\Signer\InvalidKeyProvided;
|
||||
use Lcobucci\JWT\Signer\Key;
|
||||
use Lcobucci\JWT\Token\Plain;
|
||||
use Lcobucci\JWT\Token\RegisteredClaimGiven;
|
||||
|
||||
interface Builder
|
||||
{
|
||||
/**
|
||||
* Appends new items to audience
|
||||
*/
|
||||
public function permittedFor(string ...$audiences): Builder;
|
||||
|
||||
/**
|
||||
* Configures the expiration time
|
||||
*/
|
||||
public function expiresAt(DateTimeImmutable $expiration): Builder;
|
||||
|
||||
/**
|
||||
* Configures the token id
|
||||
*/
|
||||
public function identifiedBy(string $id): Builder;
|
||||
|
||||
/**
|
||||
* Configures the time that the token was issued
|
||||
*/
|
||||
public function issuedAt(DateTimeImmutable $issuedAt): Builder;
|
||||
|
||||
/**
|
||||
* Configures the issuer
|
||||
*/
|
||||
public function issuedBy(string $issuer): Builder;
|
||||
|
||||
/**
|
||||
* Configures the time before which the token cannot be accepted
|
||||
*/
|
||||
public function canOnlyBeUsedAfter(DateTimeImmutable $notBefore): Builder;
|
||||
|
||||
/**
|
||||
* Configures the subject
|
||||
*/
|
||||
public function relatedTo(string $subject): Builder;
|
||||
|
||||
/**
|
||||
* Configures a header item
|
||||
*
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function withHeader(string $name, $value): Builder;
|
||||
|
||||
/**
|
||||
* Configures a claim item
|
||||
*
|
||||
* @param mixed $value
|
||||
*
|
||||
* @throws RegisteredClaimGiven When trying to set a registered claim.
|
||||
*/
|
||||
public function withClaim(string $name, $value): Builder;
|
||||
|
||||
/**
|
||||
* Returns a signed token to be used
|
||||
*
|
||||
* @throws CannotEncodeContent When data cannot be converted to JSON.
|
||||
* @throws CannotSignPayload When payload signing fails.
|
||||
* @throws InvalidKeyProvided When issue key is invalid/incompatible.
|
||||
* @throws ConversionFailed When signature could not be converted.
|
||||
*/
|
||||
public function getToken(Signer $signer, Key $key): Plain;
|
||||
}
|
||||
14
vendor/lcobucci/jwt/src/ClaimsFormatter.php
vendored
Normal file
14
vendor/lcobucci/jwt/src/ClaimsFormatter.php
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT;
|
||||
|
||||
interface ClaimsFormatter
|
||||
{
|
||||
/**
|
||||
* @param array<string, mixed> $claims
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function formatClaims(array $claims): array;
|
||||
}
|
||||
154
vendor/lcobucci/jwt/src/Configuration.php
vendored
Normal file
154
vendor/lcobucci/jwt/src/Configuration.php
vendored
Normal file
@@ -0,0 +1,154 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT;
|
||||
|
||||
use Closure;
|
||||
use Lcobucci\JWT\Encoding\ChainedFormatter;
|
||||
use Lcobucci\JWT\Encoding\JoseEncoder;
|
||||
use Lcobucci\JWT\Signer\Key;
|
||||
use Lcobucci\JWT\Signer\Key\InMemory;
|
||||
use Lcobucci\JWT\Signer\None;
|
||||
use Lcobucci\JWT\Validation\Constraint;
|
||||
|
||||
/**
|
||||
* Configuration container for the JWT Builder and Parser
|
||||
*
|
||||
* Serves like a small DI container to simplify the creation and usage
|
||||
* of the objects.
|
||||
*/
|
||||
final class Configuration
|
||||
{
|
||||
private Parser $parser;
|
||||
private Signer $signer;
|
||||
private Key $signingKey;
|
||||
private Key $verificationKey;
|
||||
private Validator $validator;
|
||||
|
||||
/** @var Closure(ClaimsFormatter $claimFormatter): Builder */
|
||||
private Closure $builderFactory;
|
||||
|
||||
/** @var Constraint[] */
|
||||
private array $validationConstraints = [];
|
||||
|
||||
private function __construct(
|
||||
Signer $signer,
|
||||
Key $signingKey,
|
||||
Key $verificationKey,
|
||||
?Encoder $encoder = null,
|
||||
?Decoder $decoder = null
|
||||
) {
|
||||
$this->signer = $signer;
|
||||
$this->signingKey = $signingKey;
|
||||
$this->verificationKey = $verificationKey;
|
||||
$this->parser = new Token\Parser($decoder ?? new JoseEncoder());
|
||||
$this->validator = new Validation\Validator();
|
||||
|
||||
$this->builderFactory = static function (ClaimsFormatter $claimFormatter) use ($encoder): Builder {
|
||||
return new Token\Builder($encoder ?? new JoseEncoder(), $claimFormatter);
|
||||
};
|
||||
}
|
||||
|
||||
public static function forAsymmetricSigner(
|
||||
Signer $signer,
|
||||
Key $signingKey,
|
||||
Key $verificationKey,
|
||||
?Encoder $encoder = null,
|
||||
?Decoder $decoder = null
|
||||
): self {
|
||||
return new self(
|
||||
$signer,
|
||||
$signingKey,
|
||||
$verificationKey,
|
||||
$encoder,
|
||||
$decoder
|
||||
);
|
||||
}
|
||||
|
||||
public static function forSymmetricSigner(
|
||||
Signer $signer,
|
||||
Key $key,
|
||||
?Encoder $encoder = null,
|
||||
?Decoder $decoder = null
|
||||
): self {
|
||||
return new self(
|
||||
$signer,
|
||||
$key,
|
||||
$key,
|
||||
$encoder,
|
||||
$decoder
|
||||
);
|
||||
}
|
||||
|
||||
public static function forUnsecuredSigner(
|
||||
?Encoder $encoder = null,
|
||||
?Decoder $decoder = null
|
||||
): self {
|
||||
$key = InMemory::empty();
|
||||
|
||||
return new self(
|
||||
new None(),
|
||||
$key,
|
||||
$key,
|
||||
$encoder,
|
||||
$decoder
|
||||
);
|
||||
}
|
||||
|
||||
/** @param callable(ClaimsFormatter): Builder $builderFactory */
|
||||
public function setBuilderFactory(callable $builderFactory): void
|
||||
{
|
||||
$this->builderFactory = Closure::fromCallable($builderFactory);
|
||||
}
|
||||
|
||||
public function builder(?ClaimsFormatter $claimFormatter = null): Builder
|
||||
{
|
||||
return ($this->builderFactory)($claimFormatter ?? ChainedFormatter::default());
|
||||
}
|
||||
|
||||
public function parser(): Parser
|
||||
{
|
||||
return $this->parser;
|
||||
}
|
||||
|
||||
public function setParser(Parser $parser): void
|
||||
{
|
||||
$this->parser = $parser;
|
||||
}
|
||||
|
||||
public function signer(): Signer
|
||||
{
|
||||
return $this->signer;
|
||||
}
|
||||
|
||||
public function signingKey(): Key
|
||||
{
|
||||
return $this->signingKey;
|
||||
}
|
||||
|
||||
public function verificationKey(): Key
|
||||
{
|
||||
return $this->verificationKey;
|
||||
}
|
||||
|
||||
public function validator(): Validator
|
||||
{
|
||||
return $this->validator;
|
||||
}
|
||||
|
||||
public function setValidator(Validator $validator): void
|
||||
{
|
||||
$this->validator = $validator;
|
||||
}
|
||||
|
||||
/** @return Constraint[] */
|
||||
public function validationConstraints(): array
|
||||
{
|
||||
return $this->validationConstraints;
|
||||
}
|
||||
|
||||
public function setValidationConstraints(Constraint ...$validationConstraints): void
|
||||
{
|
||||
$this->validationConstraints = $validationConstraints;
|
||||
}
|
||||
}
|
||||
27
vendor/lcobucci/jwt/src/Decoder.php
vendored
Normal file
27
vendor/lcobucci/jwt/src/Decoder.php
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT;
|
||||
|
||||
use Lcobucci\JWT\Encoding\CannotDecodeContent;
|
||||
|
||||
interface Decoder
|
||||
{
|
||||
/**
|
||||
* Decodes from JSON, validating the errors
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @throws CannotDecodeContent When something goes wrong while decoding.
|
||||
*/
|
||||
public function jsonDecode(string $json);
|
||||
|
||||
/**
|
||||
* Decodes from Base64URL
|
||||
*
|
||||
* @link http://tools.ietf.org/html/rfc4648#section-5
|
||||
*
|
||||
* @throws CannotDecodeContent When something goes wrong while decoding.
|
||||
*/
|
||||
public function base64UrlDecode(string $data): string;
|
||||
}
|
||||
25
vendor/lcobucci/jwt/src/Encoder.php
vendored
Normal file
25
vendor/lcobucci/jwt/src/Encoder.php
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT;
|
||||
|
||||
use Lcobucci\JWT\Encoding\CannotEncodeContent;
|
||||
|
||||
interface Encoder
|
||||
{
|
||||
/**
|
||||
* Encodes to JSON, validating the errors
|
||||
*
|
||||
* @param mixed $data
|
||||
*
|
||||
* @throws CannotEncodeContent When something goes wrong while encoding.
|
||||
*/
|
||||
public function jsonEncode($data): string;
|
||||
|
||||
/**
|
||||
* Encodes to base64url
|
||||
*
|
||||
* @link http://tools.ietf.org/html/rfc4648#section-5
|
||||
*/
|
||||
public function base64UrlEncode(string $data): string;
|
||||
}
|
||||
21
vendor/lcobucci/jwt/src/Encoding/CannotDecodeContent.php
vendored
Normal file
21
vendor/lcobucci/jwt/src/Encoding/CannotDecodeContent.php
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Encoding;
|
||||
|
||||
use JsonException;
|
||||
use Lcobucci\JWT\Exception;
|
||||
use RuntimeException;
|
||||
|
||||
final class CannotDecodeContent extends RuntimeException implements Exception
|
||||
{
|
||||
public static function jsonIssues(JsonException $previous): self
|
||||
{
|
||||
return new self('Error while decoding from JSON', 0, $previous);
|
||||
}
|
||||
|
||||
public static function invalidBase64String(): self
|
||||
{
|
||||
return new self('Error while decoding from Base64Url, invalid base64 characters detected');
|
||||
}
|
||||
}
|
||||
16
vendor/lcobucci/jwt/src/Encoding/CannotEncodeContent.php
vendored
Normal file
16
vendor/lcobucci/jwt/src/Encoding/CannotEncodeContent.php
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Encoding;
|
||||
|
||||
use JsonException;
|
||||
use Lcobucci\JWT\Exception;
|
||||
use RuntimeException;
|
||||
|
||||
final class CannotEncodeContent extends RuntimeException implements Exception
|
||||
{
|
||||
public static function jsonIssues(JsonException $previous): self
|
||||
{
|
||||
return new self('Error while encoding to JSON', 0, $previous);
|
||||
}
|
||||
}
|
||||
32
vendor/lcobucci/jwt/src/Encoding/ChainedFormatter.php
vendored
Normal file
32
vendor/lcobucci/jwt/src/Encoding/ChainedFormatter.php
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Encoding;
|
||||
|
||||
use Lcobucci\JWT\ClaimsFormatter;
|
||||
|
||||
final class ChainedFormatter implements ClaimsFormatter
|
||||
{
|
||||
/** @var list<ClaimsFormatter> */
|
||||
private array $formatters;
|
||||
|
||||
public function __construct(ClaimsFormatter ...$formatters)
|
||||
{
|
||||
$this->formatters = $formatters;
|
||||
}
|
||||
|
||||
public static function default(): self
|
||||
{
|
||||
return new self(new UnifyAudience(), new MicrosecondBasedDateConversion());
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
public function formatClaims(array $claims): array
|
||||
{
|
||||
foreach ($this->formatters as $formatter) {
|
||||
$claims = $formatter->formatClaims($claims);
|
||||
}
|
||||
|
||||
return $claims;
|
||||
}
|
||||
}
|
||||
65
vendor/lcobucci/jwt/src/Encoding/JoseEncoder.php
vendored
Normal file
65
vendor/lcobucci/jwt/src/Encoding/JoseEncoder.php
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Encoding;
|
||||
|
||||
use JsonException;
|
||||
use Lcobucci\JWT\Decoder;
|
||||
use Lcobucci\JWT\Encoder;
|
||||
|
||||
use function base64_decode;
|
||||
use function base64_encode;
|
||||
use function is_string;
|
||||
use function json_decode;
|
||||
use function json_encode;
|
||||
use function rtrim;
|
||||
use function strtr;
|
||||
|
||||
use const JSON_THROW_ON_ERROR;
|
||||
use const JSON_UNESCAPED_SLASHES;
|
||||
use const JSON_UNESCAPED_UNICODE;
|
||||
|
||||
/**
|
||||
* A utilitarian class that encodes and decodes data according with JOSE specifications
|
||||
*/
|
||||
final class JoseEncoder implements Encoder, Decoder
|
||||
{
|
||||
private const JSON_DEFAULT_DEPTH = 512;
|
||||
|
||||
/** @inheritdoc */
|
||||
public function jsonEncode($data): string
|
||||
{
|
||||
try {
|
||||
return json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR);
|
||||
} catch (JsonException $exception) {
|
||||
throw CannotEncodeContent::jsonIssues($exception);
|
||||
}
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
public function jsonDecode(string $json)
|
||||
{
|
||||
try {
|
||||
return json_decode($json, true, self::JSON_DEFAULT_DEPTH, JSON_THROW_ON_ERROR);
|
||||
} catch (JsonException $exception) {
|
||||
throw CannotDecodeContent::jsonIssues($exception);
|
||||
}
|
||||
}
|
||||
|
||||
public function base64UrlEncode(string $data): string
|
||||
{
|
||||
return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
|
||||
}
|
||||
|
||||
public function base64UrlDecode(string $data): string
|
||||
{
|
||||
// Padding isn't added back because it isn't strictly necessary for decoding with PHP
|
||||
$decodedContent = base64_decode(strtr($data, '-_', '+/'), true);
|
||||
|
||||
if (! is_string($decodedContent)) {
|
||||
throw CannotDecodeContent::invalidBase64String();
|
||||
}
|
||||
|
||||
return $decodedContent;
|
||||
}
|
||||
}
|
||||
37
vendor/lcobucci/jwt/src/Encoding/MicrosecondBasedDateConversion.php
vendored
Normal file
37
vendor/lcobucci/jwt/src/Encoding/MicrosecondBasedDateConversion.php
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Encoding;
|
||||
|
||||
use DateTimeImmutable;
|
||||
use Lcobucci\JWT\ClaimsFormatter;
|
||||
use Lcobucci\JWT\Token\RegisteredClaims;
|
||||
|
||||
use function array_key_exists;
|
||||
|
||||
final class MicrosecondBasedDateConversion implements ClaimsFormatter
|
||||
{
|
||||
/** @inheritdoc */
|
||||
public function formatClaims(array $claims): array
|
||||
{
|
||||
foreach (RegisteredClaims::DATE_CLAIMS as $claim) {
|
||||
if (! array_key_exists($claim, $claims)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$claims[$claim] = $this->convertDate($claims[$claim]);
|
||||
}
|
||||
|
||||
return $claims;
|
||||
}
|
||||
|
||||
/** @return int|float */
|
||||
private function convertDate(DateTimeImmutable $date)
|
||||
{
|
||||
if ($date->format('u') === '000000') {
|
||||
return (int) $date->format('U');
|
||||
}
|
||||
|
||||
return (float) $date->format('U.u');
|
||||
}
|
||||
}
|
||||
29
vendor/lcobucci/jwt/src/Encoding/UnifyAudience.php
vendored
Normal file
29
vendor/lcobucci/jwt/src/Encoding/UnifyAudience.php
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Encoding;
|
||||
|
||||
use Lcobucci\JWT\ClaimsFormatter;
|
||||
use Lcobucci\JWT\Token\RegisteredClaims;
|
||||
|
||||
use function array_key_exists;
|
||||
use function count;
|
||||
use function current;
|
||||
|
||||
final class UnifyAudience implements ClaimsFormatter
|
||||
{
|
||||
/** @inheritdoc */
|
||||
public function formatClaims(array $claims): array
|
||||
{
|
||||
if (
|
||||
! array_key_exists(RegisteredClaims::AUDIENCE, $claims)
|
||||
|| count($claims[RegisteredClaims::AUDIENCE]) !== 1
|
||||
) {
|
||||
return $claims;
|
||||
}
|
||||
|
||||
$claims[RegisteredClaims::AUDIENCE] = current($claims[RegisteredClaims::AUDIENCE]);
|
||||
|
||||
return $claims;
|
||||
}
|
||||
}
|
||||
10
vendor/lcobucci/jwt/src/Exception.php
vendored
Normal file
10
vendor/lcobucci/jwt/src/Exception.php
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT;
|
||||
|
||||
use Throwable;
|
||||
|
||||
interface Exception extends Throwable
|
||||
{
|
||||
}
|
||||
20
vendor/lcobucci/jwt/src/Parser.php
vendored
Normal file
20
vendor/lcobucci/jwt/src/Parser.php
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT;
|
||||
|
||||
use Lcobucci\JWT\Encoding\CannotDecodeContent;
|
||||
use Lcobucci\JWT\Token\InvalidTokenStructure;
|
||||
use Lcobucci\JWT\Token\UnsupportedHeaderFound;
|
||||
|
||||
interface Parser
|
||||
{
|
||||
/**
|
||||
* Parses the JWT and returns a token
|
||||
*
|
||||
* @throws CannotDecodeContent When something goes wrong while decoding.
|
||||
* @throws InvalidTokenStructure When token string structure is invalid.
|
||||
* @throws UnsupportedHeaderFound When parsed token has an unsupported header.
|
||||
*/
|
||||
public function parse(string $jwt): Token;
|
||||
}
|
||||
34
vendor/lcobucci/jwt/src/Signer.php
vendored
Normal file
34
vendor/lcobucci/jwt/src/Signer.php
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT;
|
||||
|
||||
use Lcobucci\JWT\Signer\CannotSignPayload;
|
||||
use Lcobucci\JWT\Signer\Ecdsa\ConversionFailed;
|
||||
use Lcobucci\JWT\Signer\InvalidKeyProvided;
|
||||
use Lcobucci\JWT\Signer\Key;
|
||||
|
||||
interface Signer
|
||||
{
|
||||
/**
|
||||
* Returns the algorithm id
|
||||
*/
|
||||
public function algorithmId(): string;
|
||||
|
||||
/**
|
||||
* Creates a hash for the given payload
|
||||
*
|
||||
* @throws CannotSignPayload When payload signing fails.
|
||||
* @throws InvalidKeyProvided When issue key is invalid/incompatible.
|
||||
* @throws ConversionFailed When signature could not be converted.
|
||||
*/
|
||||
public function sign(string $payload, Key $key): string;
|
||||
|
||||
/**
|
||||
* Returns if the expected hash matches with the data and key
|
||||
*
|
||||
* @throws InvalidKeyProvided When issue key is invalid/incompatible.
|
||||
* @throws ConversionFailed When signature could not be converted.
|
||||
*/
|
||||
public function verify(string $expected, string $payload, Key $key): bool;
|
||||
}
|
||||
15
vendor/lcobucci/jwt/src/Signer/CannotSignPayload.php
vendored
Normal file
15
vendor/lcobucci/jwt/src/Signer/CannotSignPayload.php
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Signer;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use Lcobucci\JWT\Exception;
|
||||
|
||||
final class CannotSignPayload extends InvalidArgumentException implements Exception
|
||||
{
|
||||
public static function errorHappened(string $error): self
|
||||
{
|
||||
return new self('There was an error while creating the signature: ' . $error);
|
||||
}
|
||||
}
|
||||
53
vendor/lcobucci/jwt/src/Signer/Ecdsa.php
vendored
Normal file
53
vendor/lcobucci/jwt/src/Signer/Ecdsa.php
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Signer;
|
||||
|
||||
use Lcobucci\JWT\Signer\Ecdsa\MultibyteStringConverter;
|
||||
use Lcobucci\JWT\Signer\Ecdsa\SignatureConverter;
|
||||
|
||||
use const OPENSSL_KEYTYPE_EC;
|
||||
|
||||
abstract class Ecdsa extends OpenSSL
|
||||
{
|
||||
private SignatureConverter $converter;
|
||||
|
||||
public function __construct(SignatureConverter $converter)
|
||||
{
|
||||
$this->converter = $converter;
|
||||
}
|
||||
|
||||
public static function create(): Ecdsa
|
||||
{
|
||||
return new static(new MultibyteStringConverter()); // @phpstan-ignore-line
|
||||
}
|
||||
|
||||
final public function sign(string $payload, Key $key): string
|
||||
{
|
||||
return $this->converter->fromAsn1(
|
||||
$this->createSignature($key->contents(), $key->passphrase(), $payload),
|
||||
$this->keyLength()
|
||||
);
|
||||
}
|
||||
|
||||
final public function verify(string $expected, string $payload, Key $key): bool
|
||||
{
|
||||
return $this->verifySignature(
|
||||
$this->converter->toAsn1($expected, $this->keyLength()),
|
||||
$payload,
|
||||
$key->contents()
|
||||
);
|
||||
}
|
||||
|
||||
final public function keyType(): int
|
||||
{
|
||||
return OPENSSL_KEYTYPE_EC;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the length of each point in the signature, so that we can calculate and verify R and S points properly
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
abstract public function keyLength(): int;
|
||||
}
|
||||
25
vendor/lcobucci/jwt/src/Signer/Ecdsa/ConversionFailed.php
vendored
Normal file
25
vendor/lcobucci/jwt/src/Signer/Ecdsa/ConversionFailed.php
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Signer\Ecdsa;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use Lcobucci\JWT\Exception;
|
||||
|
||||
final class ConversionFailed extends InvalidArgumentException implements Exception
|
||||
{
|
||||
public static function invalidLength(): self
|
||||
{
|
||||
return new self('Invalid signature length.');
|
||||
}
|
||||
|
||||
public static function incorrectStartSequence(): self
|
||||
{
|
||||
return new self('Invalid data. Should start with a sequence.');
|
||||
}
|
||||
|
||||
public static function integerExpected(): self
|
||||
{
|
||||
return new self('Invalid data. Should contain an integer.');
|
||||
}
|
||||
}
|
||||
146
vendor/lcobucci/jwt/src/Signer/Ecdsa/MultibyteStringConverter.php
vendored
Normal file
146
vendor/lcobucci/jwt/src/Signer/Ecdsa/MultibyteStringConverter.php
vendored
Normal file
@@ -0,0 +1,146 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014-2018 Spomky-Labs
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*
|
||||
* @link https://github.com/web-token/jwt-framework/blob/v1.2/src/Component/Core/Util/ECSignature.php
|
||||
*/
|
||||
|
||||
namespace Lcobucci\JWT\Signer\Ecdsa;
|
||||
|
||||
use function assert;
|
||||
use function bin2hex;
|
||||
use function dechex;
|
||||
use function hex2bin;
|
||||
use function hexdec;
|
||||
use function is_string;
|
||||
use function mb_strlen;
|
||||
use function mb_substr;
|
||||
use function str_pad;
|
||||
|
||||
use const STR_PAD_LEFT;
|
||||
|
||||
/**
|
||||
* ECDSA signature converter using ext-mbstring
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class MultibyteStringConverter implements SignatureConverter
|
||||
{
|
||||
private const ASN1_SEQUENCE = '30';
|
||||
private const ASN1_INTEGER = '02';
|
||||
private const ASN1_MAX_SINGLE_BYTE = 128;
|
||||
private const ASN1_LENGTH_2BYTES = '81';
|
||||
private const ASN1_BIG_INTEGER_LIMIT = '7f';
|
||||
private const ASN1_NEGATIVE_INTEGER = '00';
|
||||
private const BYTE_SIZE = 2;
|
||||
|
||||
public function toAsn1(string $points, int $length): string
|
||||
{
|
||||
$points = bin2hex($points);
|
||||
|
||||
if (self::octetLength($points) !== $length) {
|
||||
throw ConversionFailed::invalidLength();
|
||||
}
|
||||
|
||||
$pointR = self::preparePositiveInteger(mb_substr($points, 0, $length, '8bit'));
|
||||
$pointS = self::preparePositiveInteger(mb_substr($points, $length, null, '8bit'));
|
||||
|
||||
$lengthR = self::octetLength($pointR);
|
||||
$lengthS = self::octetLength($pointS);
|
||||
|
||||
$totalLength = $lengthR + $lengthS + self::BYTE_SIZE + self::BYTE_SIZE;
|
||||
$lengthPrefix = $totalLength > self::ASN1_MAX_SINGLE_BYTE ? self::ASN1_LENGTH_2BYTES : '';
|
||||
|
||||
$asn1 = hex2bin(
|
||||
self::ASN1_SEQUENCE
|
||||
. $lengthPrefix . dechex($totalLength)
|
||||
. self::ASN1_INTEGER . dechex($lengthR) . $pointR
|
||||
. self::ASN1_INTEGER . dechex($lengthS) . $pointS
|
||||
);
|
||||
assert(is_string($asn1));
|
||||
|
||||
return $asn1;
|
||||
}
|
||||
|
||||
private static function octetLength(string $data): int
|
||||
{
|
||||
return (int) (mb_strlen($data, '8bit') / self::BYTE_SIZE);
|
||||
}
|
||||
|
||||
private static function preparePositiveInteger(string $data): string
|
||||
{
|
||||
if (mb_substr($data, 0, self::BYTE_SIZE, '8bit') > self::ASN1_BIG_INTEGER_LIMIT) {
|
||||
return self::ASN1_NEGATIVE_INTEGER . $data;
|
||||
}
|
||||
|
||||
while (
|
||||
mb_substr($data, 0, self::BYTE_SIZE, '8bit') === self::ASN1_NEGATIVE_INTEGER
|
||||
&& mb_substr($data, 2, self::BYTE_SIZE, '8bit') <= self::ASN1_BIG_INTEGER_LIMIT
|
||||
) {
|
||||
$data = mb_substr($data, 2, null, '8bit');
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function fromAsn1(string $signature, int $length): string
|
||||
{
|
||||
$message = bin2hex($signature);
|
||||
$position = 0;
|
||||
|
||||
if (self::readAsn1Content($message, $position, self::BYTE_SIZE) !== self::ASN1_SEQUENCE) {
|
||||
throw ConversionFailed::incorrectStartSequence();
|
||||
}
|
||||
|
||||
// @phpstan-ignore-next-line
|
||||
if (self::readAsn1Content($message, $position, self::BYTE_SIZE) === self::ASN1_LENGTH_2BYTES) {
|
||||
$position += self::BYTE_SIZE;
|
||||
}
|
||||
|
||||
$pointR = self::retrievePositiveInteger(self::readAsn1Integer($message, $position));
|
||||
$pointS = self::retrievePositiveInteger(self::readAsn1Integer($message, $position));
|
||||
|
||||
$points = hex2bin(str_pad($pointR, $length, '0', STR_PAD_LEFT) . str_pad($pointS, $length, '0', STR_PAD_LEFT));
|
||||
assert(is_string($points));
|
||||
|
||||
return $points;
|
||||
}
|
||||
|
||||
private static function readAsn1Content(string $message, int &$position, int $length): string
|
||||
{
|
||||
$content = mb_substr($message, $position, $length, '8bit');
|
||||
$position += $length;
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
private static function readAsn1Integer(string $message, int &$position): string
|
||||
{
|
||||
if (self::readAsn1Content($message, $position, self::BYTE_SIZE) !== self::ASN1_INTEGER) {
|
||||
throw ConversionFailed::integerExpected();
|
||||
}
|
||||
|
||||
$length = (int) hexdec(self::readAsn1Content($message, $position, self::BYTE_SIZE));
|
||||
|
||||
return self::readAsn1Content($message, $position, $length * self::BYTE_SIZE);
|
||||
}
|
||||
|
||||
private static function retrievePositiveInteger(string $data): string
|
||||
{
|
||||
while (
|
||||
mb_substr($data, 0, self::BYTE_SIZE, '8bit') === self::ASN1_NEGATIVE_INTEGER
|
||||
&& mb_substr($data, 2, self::BYTE_SIZE, '8bit') > self::ASN1_BIG_INTEGER_LIMIT
|
||||
) {
|
||||
$data = mb_substr($data, 2, null, '8bit');
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
26
vendor/lcobucci/jwt/src/Signer/Ecdsa/Sha256.php
vendored
Normal file
26
vendor/lcobucci/jwt/src/Signer/Ecdsa/Sha256.php
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Signer\Ecdsa;
|
||||
|
||||
use Lcobucci\JWT\Signer\Ecdsa;
|
||||
|
||||
use const OPENSSL_ALGO_SHA256;
|
||||
|
||||
final class Sha256 extends Ecdsa
|
||||
{
|
||||
public function algorithmId(): string
|
||||
{
|
||||
return 'ES256';
|
||||
}
|
||||
|
||||
public function algorithm(): int
|
||||
{
|
||||
return OPENSSL_ALGO_SHA256;
|
||||
}
|
||||
|
||||
public function keyLength(): int
|
||||
{
|
||||
return 64;
|
||||
}
|
||||
}
|
||||
26
vendor/lcobucci/jwt/src/Signer/Ecdsa/Sha384.php
vendored
Normal file
26
vendor/lcobucci/jwt/src/Signer/Ecdsa/Sha384.php
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Signer\Ecdsa;
|
||||
|
||||
use Lcobucci\JWT\Signer\Ecdsa;
|
||||
|
||||
use const OPENSSL_ALGO_SHA384;
|
||||
|
||||
final class Sha384 extends Ecdsa
|
||||
{
|
||||
public function algorithmId(): string
|
||||
{
|
||||
return 'ES384';
|
||||
}
|
||||
|
||||
public function algorithm(): int
|
||||
{
|
||||
return OPENSSL_ALGO_SHA384;
|
||||
}
|
||||
|
||||
public function keyLength(): int
|
||||
{
|
||||
return 96;
|
||||
}
|
||||
}
|
||||
26
vendor/lcobucci/jwt/src/Signer/Ecdsa/Sha512.php
vendored
Normal file
26
vendor/lcobucci/jwt/src/Signer/Ecdsa/Sha512.php
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Signer\Ecdsa;
|
||||
|
||||
use Lcobucci\JWT\Signer\Ecdsa;
|
||||
|
||||
use const OPENSSL_ALGO_SHA512;
|
||||
|
||||
final class Sha512 extends Ecdsa
|
||||
{
|
||||
public function algorithmId(): string
|
||||
{
|
||||
return 'ES512';
|
||||
}
|
||||
|
||||
public function algorithm(): int
|
||||
{
|
||||
return OPENSSL_ALGO_SHA512;
|
||||
}
|
||||
|
||||
public function keyLength(): int
|
||||
{
|
||||
return 132;
|
||||
}
|
||||
}
|
||||
34
vendor/lcobucci/jwt/src/Signer/Ecdsa/SignatureConverter.php
vendored
Normal file
34
vendor/lcobucci/jwt/src/Signer/Ecdsa/SignatureConverter.php
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Signer\Ecdsa;
|
||||
|
||||
/**
|
||||
* Manipulates the result of a ECDSA signature (points R and S) according to the
|
||||
* JWA specs.
|
||||
*
|
||||
* OpenSSL creates a signature using the ASN.1 format and, according the JWA specs,
|
||||
* the signature for JWTs must be the concatenated values of points R and S (in
|
||||
* big-endian octet order).
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc7518#page-9
|
||||
* @see https://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One
|
||||
*/
|
||||
interface SignatureConverter
|
||||
{
|
||||
/**
|
||||
* Converts the signature generated by OpenSSL into what JWA defines
|
||||
*
|
||||
* @throws ConversionFailed When there was an issue during the format conversion.
|
||||
*/
|
||||
public function fromAsn1(string $signature, int $length): string;
|
||||
|
||||
/**
|
||||
* Converts the JWA signature into something OpenSSL understands
|
||||
*
|
||||
* @throws ConversionFailed When there was an issue during the format conversion.
|
||||
*/
|
||||
public function toAsn1(string $points, int $length): string;
|
||||
}
|
||||
24
vendor/lcobucci/jwt/src/Signer/Hmac.php
vendored
Normal file
24
vendor/lcobucci/jwt/src/Signer/Hmac.php
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Signer;
|
||||
|
||||
use Lcobucci\JWT\Signer;
|
||||
|
||||
use function hash_equals;
|
||||
use function hash_hmac;
|
||||
|
||||
abstract class Hmac implements Signer
|
||||
{
|
||||
final public function sign(string $payload, Key $key): string
|
||||
{
|
||||
return hash_hmac($this->algorithm(), $payload, $key->contents(), true);
|
||||
}
|
||||
|
||||
final public function verify(string $expected, string $payload, Key $key): bool
|
||||
{
|
||||
return hash_equals($expected, $this->sign($payload, $key));
|
||||
}
|
||||
|
||||
abstract public function algorithm(): string;
|
||||
}
|
||||
19
vendor/lcobucci/jwt/src/Signer/Hmac/Sha256.php
vendored
Normal file
19
vendor/lcobucci/jwt/src/Signer/Hmac/Sha256.php
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Signer\Hmac;
|
||||
|
||||
use Lcobucci\JWT\Signer\Hmac;
|
||||
|
||||
final class Sha256 extends Hmac
|
||||
{
|
||||
public function algorithmId(): string
|
||||
{
|
||||
return 'HS256';
|
||||
}
|
||||
|
||||
public function algorithm(): string
|
||||
{
|
||||
return 'sha256';
|
||||
}
|
||||
}
|
||||
19
vendor/lcobucci/jwt/src/Signer/Hmac/Sha384.php
vendored
Normal file
19
vendor/lcobucci/jwt/src/Signer/Hmac/Sha384.php
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Signer\Hmac;
|
||||
|
||||
use Lcobucci\JWT\Signer\Hmac;
|
||||
|
||||
final class Sha384 extends Hmac
|
||||
{
|
||||
public function algorithmId(): string
|
||||
{
|
||||
return 'HS384';
|
||||
}
|
||||
|
||||
public function algorithm(): string
|
||||
{
|
||||
return 'sha384';
|
||||
}
|
||||
}
|
||||
19
vendor/lcobucci/jwt/src/Signer/Hmac/Sha512.php
vendored
Normal file
19
vendor/lcobucci/jwt/src/Signer/Hmac/Sha512.php
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Signer\Hmac;
|
||||
|
||||
use Lcobucci\JWT\Signer\Hmac;
|
||||
|
||||
final class Sha512 extends Hmac
|
||||
{
|
||||
public function algorithmId(): string
|
||||
{
|
||||
return 'HS512';
|
||||
}
|
||||
|
||||
public function algorithm(): string
|
||||
{
|
||||
return 'sha512';
|
||||
}
|
||||
}
|
||||
20
vendor/lcobucci/jwt/src/Signer/InvalidKeyProvided.php
vendored
Normal file
20
vendor/lcobucci/jwt/src/Signer/InvalidKeyProvided.php
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Signer;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use Lcobucci\JWT\Exception;
|
||||
|
||||
final class InvalidKeyProvided extends InvalidArgumentException implements Exception
|
||||
{
|
||||
public static function cannotBeParsed(string $details): self
|
||||
{
|
||||
return new self('It was not possible to parse your key, reason: ' . $details);
|
||||
}
|
||||
|
||||
public static function incompatibleKey(): self
|
||||
{
|
||||
return new self('This key is not compatible with this signer');
|
||||
}
|
||||
}
|
||||
11
vendor/lcobucci/jwt/src/Signer/Key.php
vendored
Normal file
11
vendor/lcobucci/jwt/src/Signer/Key.php
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Signer;
|
||||
|
||||
interface Key
|
||||
{
|
||||
public function contents(): string;
|
||||
|
||||
public function passphrase(): string;
|
||||
}
|
||||
20
vendor/lcobucci/jwt/src/Signer/Key/FileCouldNotBeRead.php
vendored
Normal file
20
vendor/lcobucci/jwt/src/Signer/Key/FileCouldNotBeRead.php
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Signer\Key;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use Lcobucci\JWT\Exception;
|
||||
use Throwable;
|
||||
|
||||
final class FileCouldNotBeRead extends InvalidArgumentException implements Exception
|
||||
{
|
||||
public static function onPath(string $path, ?Throwable $cause = null): self
|
||||
{
|
||||
return new self(
|
||||
'The path "' . $path . '" does not contain a valid key file',
|
||||
0,
|
||||
$cause
|
||||
);
|
||||
}
|
||||
}
|
||||
71
vendor/lcobucci/jwt/src/Signer/Key/InMemory.php
vendored
Normal file
71
vendor/lcobucci/jwt/src/Signer/Key/InMemory.php
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Signer\Key;
|
||||
|
||||
use Lcobucci\JWT\Encoding\CannotDecodeContent;
|
||||
use Lcobucci\JWT\Signer\Key;
|
||||
use SplFileObject;
|
||||
use Throwable;
|
||||
|
||||
use function assert;
|
||||
use function base64_decode;
|
||||
use function is_string;
|
||||
|
||||
final class InMemory implements Key
|
||||
{
|
||||
private string $contents;
|
||||
private string $passphrase;
|
||||
|
||||
private function __construct(string $contents, string $passphrase)
|
||||
{
|
||||
$this->contents = $contents;
|
||||
$this->passphrase = $passphrase;
|
||||
}
|
||||
|
||||
public static function empty(): self
|
||||
{
|
||||
return new self('', '');
|
||||
}
|
||||
|
||||
public static function plainText(string $contents, string $passphrase = ''): self
|
||||
{
|
||||
return new self($contents, $passphrase);
|
||||
}
|
||||
|
||||
public static function base64Encoded(string $contents, string $passphrase = ''): self
|
||||
{
|
||||
$decoded = base64_decode($contents, true);
|
||||
|
||||
if ($decoded === false) {
|
||||
throw CannotDecodeContent::invalidBase64String();
|
||||
}
|
||||
|
||||
return new self($decoded, $passphrase);
|
||||
}
|
||||
|
||||
/** @throws FileCouldNotBeRead */
|
||||
public static function file(string $path, string $passphrase = ''): self
|
||||
{
|
||||
try {
|
||||
$file = new SplFileObject($path);
|
||||
} catch (Throwable $exception) {
|
||||
throw FileCouldNotBeRead::onPath($path, $exception);
|
||||
}
|
||||
|
||||
$contents = $file->fread($file->getSize());
|
||||
assert(is_string($contents));
|
||||
|
||||
return new self($contents, $passphrase);
|
||||
}
|
||||
|
||||
public function contents(): string
|
||||
{
|
||||
return $this->contents;
|
||||
}
|
||||
|
||||
public function passphrase(): string
|
||||
{
|
||||
return $this->passphrase;
|
||||
}
|
||||
}
|
||||
54
vendor/lcobucci/jwt/src/Signer/Key/LocalFileReference.php
vendored
Normal file
54
vendor/lcobucci/jwt/src/Signer/Key/LocalFileReference.php
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Signer\Key;
|
||||
|
||||
use Lcobucci\JWT\Signer\Key;
|
||||
|
||||
use function file_exists;
|
||||
use function strpos;
|
||||
use function substr;
|
||||
|
||||
/** @deprecated please use {@see InMemory} instead */
|
||||
final class LocalFileReference implements Key
|
||||
{
|
||||
private const PATH_PREFIX = 'file://';
|
||||
|
||||
private string $path;
|
||||
private string $passphrase;
|
||||
private string $contents;
|
||||
|
||||
private function __construct(string $path, string $passphrase)
|
||||
{
|
||||
$this->path = $path;
|
||||
$this->passphrase = $passphrase;
|
||||
}
|
||||
|
||||
/** @throws FileCouldNotBeRead */
|
||||
public static function file(string $path, string $passphrase = ''): self
|
||||
{
|
||||
if (strpos($path, self::PATH_PREFIX) === 0) {
|
||||
$path = substr($path, 7);
|
||||
}
|
||||
|
||||
if (! file_exists($path)) {
|
||||
throw FileCouldNotBeRead::onPath($path);
|
||||
}
|
||||
|
||||
return new self($path, $passphrase);
|
||||
}
|
||||
|
||||
public function contents(): string
|
||||
{
|
||||
if (! isset($this->contents)) {
|
||||
$this->contents = InMemory::file($this->path)->contents();
|
||||
}
|
||||
|
||||
return $this->contents;
|
||||
}
|
||||
|
||||
public function passphrase(): string
|
||||
{
|
||||
return $this->passphrase;
|
||||
}
|
||||
}
|
||||
26
vendor/lcobucci/jwt/src/Signer/None.php
vendored
Normal file
26
vendor/lcobucci/jwt/src/Signer/None.php
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Signer;
|
||||
|
||||
use Lcobucci\JWT\Signer;
|
||||
|
||||
final class None implements Signer
|
||||
{
|
||||
public function algorithmId(): string
|
||||
{
|
||||
return 'none';
|
||||
}
|
||||
|
||||
// @phpcs:ignore SlevomatCodingStandard.Functions.UnusedParameter.UnusedParameter
|
||||
public function sign(string $payload, Key $key): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
// @phpcs:ignore SlevomatCodingStandard.Functions.UnusedParameter.UnusedParameter
|
||||
public function verify(string $expected, string $payload, Key $key): bool
|
||||
{
|
||||
return $expected === '';
|
||||
}
|
||||
}
|
||||
137
vendor/lcobucci/jwt/src/Signer/OpenSSL.php
vendored
Normal file
137
vendor/lcobucci/jwt/src/Signer/OpenSSL.php
vendored
Normal file
@@ -0,0 +1,137 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Signer;
|
||||
|
||||
use Lcobucci\JWT\Signer;
|
||||
use OpenSSLAsymmetricKey;
|
||||
|
||||
use function array_key_exists;
|
||||
use function assert;
|
||||
use function is_array;
|
||||
use function is_bool;
|
||||
use function is_string;
|
||||
use function openssl_error_string;
|
||||
use function openssl_free_key;
|
||||
use function openssl_pkey_get_details;
|
||||
use function openssl_pkey_get_private;
|
||||
use function openssl_pkey_get_public;
|
||||
use function openssl_sign;
|
||||
use function openssl_verify;
|
||||
|
||||
abstract class OpenSSL implements Signer
|
||||
{
|
||||
/**
|
||||
* @throws CannotSignPayload
|
||||
* @throws InvalidKeyProvided
|
||||
*/
|
||||
final protected function createSignature(
|
||||
string $pem,
|
||||
string $passphrase,
|
||||
string $payload
|
||||
): string {
|
||||
$key = $this->getPrivateKey($pem, $passphrase);
|
||||
|
||||
try {
|
||||
$signature = '';
|
||||
|
||||
if (! openssl_sign($payload, $signature, $key, $this->algorithm())) {
|
||||
$error = openssl_error_string();
|
||||
assert(is_string($error));
|
||||
|
||||
throw CannotSignPayload::errorHappened($error);
|
||||
}
|
||||
|
||||
return $signature;
|
||||
} finally {
|
||||
$this->freeKey($key);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return resource|OpenSSLAsymmetricKey
|
||||
*
|
||||
* @throws CannotSignPayload
|
||||
*/
|
||||
private function getPrivateKey(string $pem, string $passphrase)
|
||||
{
|
||||
$privateKey = openssl_pkey_get_private($pem, $passphrase);
|
||||
$this->validateKey($privateKey);
|
||||
|
||||
return $privateKey;
|
||||
}
|
||||
|
||||
/** @throws InvalidKeyProvided */
|
||||
final protected function verifySignature(
|
||||
string $expected,
|
||||
string $payload,
|
||||
string $pem
|
||||
): bool {
|
||||
$key = $this->getPublicKey($pem);
|
||||
$result = openssl_verify($payload, $expected, $key, $this->algorithm());
|
||||
$this->freeKey($key);
|
||||
|
||||
return $result === 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return resource|OpenSSLAsymmetricKey
|
||||
*
|
||||
* @throws InvalidKeyProvided
|
||||
*/
|
||||
private function getPublicKey(string $pem)
|
||||
{
|
||||
$publicKey = openssl_pkey_get_public($pem);
|
||||
$this->validateKey($publicKey);
|
||||
|
||||
return $publicKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Raises an exception when the key type is not the expected type
|
||||
*
|
||||
* @param resource|OpenSSLAsymmetricKey|bool $key
|
||||
*
|
||||
* @throws InvalidKeyProvided
|
||||
*/
|
||||
private function validateKey($key): void
|
||||
{
|
||||
if (is_bool($key)) {
|
||||
$error = openssl_error_string();
|
||||
assert(is_string($error));
|
||||
|
||||
throw InvalidKeyProvided::cannotBeParsed($error);
|
||||
}
|
||||
|
||||
$details = openssl_pkey_get_details($key);
|
||||
assert(is_array($details));
|
||||
|
||||
if (! array_key_exists('key', $details) || $details['type'] !== $this->keyType()) {
|
||||
throw InvalidKeyProvided::incompatibleKey();
|
||||
}
|
||||
}
|
||||
|
||||
/** @param resource|OpenSSLAsymmetricKey $key */
|
||||
private function freeKey($key): void
|
||||
{
|
||||
if ($key instanceof OpenSSLAsymmetricKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
openssl_free_key($key); // Deprecated and no longer necessary as of PHP >= 8.0
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of key to be used to create/verify the signature (using OpenSSL constants)
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
abstract public function keyType(): int;
|
||||
|
||||
/**
|
||||
* Returns which algorithm to be used to create/verify the signature (using OpenSSL constants)
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
abstract public function algorithm(): int;
|
||||
}
|
||||
24
vendor/lcobucci/jwt/src/Signer/Rsa.php
vendored
Normal file
24
vendor/lcobucci/jwt/src/Signer/Rsa.php
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Signer;
|
||||
|
||||
use const OPENSSL_KEYTYPE_RSA;
|
||||
|
||||
abstract class Rsa extends OpenSSL
|
||||
{
|
||||
final public function sign(string $payload, Key $key): string
|
||||
{
|
||||
return $this->createSignature($key->contents(), $key->passphrase(), $payload);
|
||||
}
|
||||
|
||||
final public function verify(string $expected, string $payload, Key $key): bool
|
||||
{
|
||||
return $this->verifySignature($expected, $payload, $key->contents());
|
||||
}
|
||||
|
||||
final public function keyType(): int
|
||||
{
|
||||
return OPENSSL_KEYTYPE_RSA;
|
||||
}
|
||||
}
|
||||
21
vendor/lcobucci/jwt/src/Signer/Rsa/Sha256.php
vendored
Normal file
21
vendor/lcobucci/jwt/src/Signer/Rsa/Sha256.php
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Signer\Rsa;
|
||||
|
||||
use Lcobucci\JWT\Signer\Rsa;
|
||||
|
||||
use const OPENSSL_ALGO_SHA256;
|
||||
|
||||
final class Sha256 extends Rsa
|
||||
{
|
||||
public function algorithmId(): string
|
||||
{
|
||||
return 'RS256';
|
||||
}
|
||||
|
||||
public function algorithm(): int
|
||||
{
|
||||
return OPENSSL_ALGO_SHA256;
|
||||
}
|
||||
}
|
||||
21
vendor/lcobucci/jwt/src/Signer/Rsa/Sha384.php
vendored
Normal file
21
vendor/lcobucci/jwt/src/Signer/Rsa/Sha384.php
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Signer\Rsa;
|
||||
|
||||
use Lcobucci\JWT\Signer\Rsa;
|
||||
|
||||
use const OPENSSL_ALGO_SHA384;
|
||||
|
||||
final class Sha384 extends Rsa
|
||||
{
|
||||
public function algorithmId(): string
|
||||
{
|
||||
return 'RS384';
|
||||
}
|
||||
|
||||
public function algorithm(): int
|
||||
{
|
||||
return OPENSSL_ALGO_SHA384;
|
||||
}
|
||||
}
|
||||
21
vendor/lcobucci/jwt/src/Signer/Rsa/Sha512.php
vendored
Normal file
21
vendor/lcobucci/jwt/src/Signer/Rsa/Sha512.php
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Signer\Rsa;
|
||||
|
||||
use Lcobucci\JWT\Signer\Rsa;
|
||||
|
||||
use const OPENSSL_ALGO_SHA512;
|
||||
|
||||
final class Sha512 extends Rsa
|
||||
{
|
||||
public function algorithmId(): string
|
||||
{
|
||||
return 'RS512';
|
||||
}
|
||||
|
||||
public function algorithm(): int
|
||||
{
|
||||
return OPENSSL_ALGO_SHA512;
|
||||
}
|
||||
}
|
||||
55
vendor/lcobucci/jwt/src/Token.php
vendored
Normal file
55
vendor/lcobucci/jwt/src/Token.php
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT;
|
||||
|
||||
use DateTimeInterface;
|
||||
use Lcobucci\JWT\Token\DataSet;
|
||||
|
||||
interface Token
|
||||
{
|
||||
/**
|
||||
* Returns the token headers
|
||||
*/
|
||||
public function headers(): DataSet;
|
||||
|
||||
/**
|
||||
* Returns if the token is allowed to be used by the audience
|
||||
*/
|
||||
public function isPermittedFor(string $audience): bool;
|
||||
|
||||
/**
|
||||
* Returns if the token has the given id
|
||||
*/
|
||||
public function isIdentifiedBy(string $id): bool;
|
||||
|
||||
/**
|
||||
* Returns if the token has the given subject
|
||||
*/
|
||||
public function isRelatedTo(string $subject): bool;
|
||||
|
||||
/**
|
||||
* Returns if the token was issued by any of given issuers
|
||||
*/
|
||||
public function hasBeenIssuedBy(string ...$issuers): bool;
|
||||
|
||||
/**
|
||||
* Returns if the token was issued before of given time
|
||||
*/
|
||||
public function hasBeenIssuedBefore(DateTimeInterface $now): bool;
|
||||
|
||||
/**
|
||||
* Returns if the token minimum time is before than given time
|
||||
*/
|
||||
public function isMinimumTimeBefore(DateTimeInterface $now): bool;
|
||||
|
||||
/**
|
||||
* Returns if the token is expired
|
||||
*/
|
||||
public function isExpired(DateTimeInterface $now): bool;
|
||||
|
||||
/**
|
||||
* Returns an encoded representation of the token
|
||||
*/
|
||||
public function toString(): string;
|
||||
}
|
||||
128
vendor/lcobucci/jwt/src/Token/Builder.php
vendored
Normal file
128
vendor/lcobucci/jwt/src/Token/Builder.php
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Token;
|
||||
|
||||
use DateTimeImmutable;
|
||||
use Lcobucci\JWT\Builder as BuilderInterface;
|
||||
use Lcobucci\JWT\ClaimsFormatter;
|
||||
use Lcobucci\JWT\Encoder;
|
||||
use Lcobucci\JWT\Encoding\CannotEncodeContent;
|
||||
use Lcobucci\JWT\Signer;
|
||||
use Lcobucci\JWT\Signer\Key;
|
||||
|
||||
use function array_diff;
|
||||
use function array_merge;
|
||||
use function in_array;
|
||||
|
||||
final class Builder implements BuilderInterface
|
||||
{
|
||||
/** @var array<string, mixed> */
|
||||
private array $headers = ['typ' => 'JWT', 'alg' => null];
|
||||
|
||||
/** @var array<string, mixed> */
|
||||
private array $claims = [];
|
||||
|
||||
private Encoder $encoder;
|
||||
private ClaimsFormatter $claimFormatter;
|
||||
|
||||
public function __construct(Encoder $encoder, ClaimsFormatter $claimFormatter)
|
||||
{
|
||||
$this->encoder = $encoder;
|
||||
$this->claimFormatter = $claimFormatter;
|
||||
}
|
||||
|
||||
public function permittedFor(string ...$audiences): BuilderInterface
|
||||
{
|
||||
$configured = $this->claims[RegisteredClaims::AUDIENCE] ?? [];
|
||||
$toAppend = array_diff($audiences, $configured);
|
||||
|
||||
return $this->setClaim(RegisteredClaims::AUDIENCE, array_merge($configured, $toAppend));
|
||||
}
|
||||
|
||||
public function expiresAt(DateTimeImmutable $expiration): BuilderInterface
|
||||
{
|
||||
return $this->setClaim(RegisteredClaims::EXPIRATION_TIME, $expiration);
|
||||
}
|
||||
|
||||
public function identifiedBy(string $id): BuilderInterface
|
||||
{
|
||||
return $this->setClaim(RegisteredClaims::ID, $id);
|
||||
}
|
||||
|
||||
public function issuedAt(DateTimeImmutable $issuedAt): BuilderInterface
|
||||
{
|
||||
return $this->setClaim(RegisteredClaims::ISSUED_AT, $issuedAt);
|
||||
}
|
||||
|
||||
public function issuedBy(string $issuer): BuilderInterface
|
||||
{
|
||||
return $this->setClaim(RegisteredClaims::ISSUER, $issuer);
|
||||
}
|
||||
|
||||
public function canOnlyBeUsedAfter(DateTimeImmutable $notBefore): BuilderInterface
|
||||
{
|
||||
return $this->setClaim(RegisteredClaims::NOT_BEFORE, $notBefore);
|
||||
}
|
||||
|
||||
public function relatedTo(string $subject): BuilderInterface
|
||||
{
|
||||
return $this->setClaim(RegisteredClaims::SUBJECT, $subject);
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
public function withHeader(string $name, $value): BuilderInterface
|
||||
{
|
||||
$this->headers[$name] = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
public function withClaim(string $name, $value): BuilderInterface
|
||||
{
|
||||
if (in_array($name, RegisteredClaims::ALL, true)) {
|
||||
throw RegisteredClaimGiven::forClaim($name);
|
||||
}
|
||||
|
||||
return $this->setClaim($name, $value);
|
||||
}
|
||||
|
||||
/** @param mixed $value */
|
||||
private function setClaim(string $name, $value): BuilderInterface
|
||||
{
|
||||
$this->claims[$name] = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $items
|
||||
*
|
||||
* @throws CannotEncodeContent When data cannot be converted to JSON.
|
||||
*/
|
||||
private function encode(array $items): string
|
||||
{
|
||||
return $this->encoder->base64UrlEncode(
|
||||
$this->encoder->jsonEncode($items)
|
||||
);
|
||||
}
|
||||
|
||||
public function getToken(Signer $signer, Key $key): Plain
|
||||
{
|
||||
$headers = $this->headers;
|
||||
$headers['alg'] = $signer->algorithmId();
|
||||
|
||||
$encodedHeaders = $this->encode($headers);
|
||||
$encodedClaims = $this->encode($this->claimFormatter->formatClaims($this->claims));
|
||||
|
||||
$signature = $signer->sign($encodedHeaders . '.' . $encodedClaims, $key);
|
||||
$encodedSignature = $this->encoder->base64UrlEncode($signature);
|
||||
|
||||
return new Plain(
|
||||
new DataSet($headers, $encodedHeaders),
|
||||
new DataSet($this->claims, $encodedClaims),
|
||||
new Signature($signature, $encodedSignature)
|
||||
);
|
||||
}
|
||||
}
|
||||
46
vendor/lcobucci/jwt/src/Token/DataSet.php
vendored
Normal file
46
vendor/lcobucci/jwt/src/Token/DataSet.php
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Token;
|
||||
|
||||
use function array_key_exists;
|
||||
|
||||
final class DataSet
|
||||
{
|
||||
/** @var array<string, mixed> */
|
||||
private array $data;
|
||||
private string $encoded;
|
||||
|
||||
/** @param mixed[] $data */
|
||||
public function __construct(array $data, string $encoded)
|
||||
{
|
||||
$this->data = $data;
|
||||
$this->encoded = $encoded;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed|null $default
|
||||
*
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function get(string $name, $default = null)
|
||||
{
|
||||
return $this->data[$name] ?? $default;
|
||||
}
|
||||
|
||||
public function has(string $name): bool
|
||||
{
|
||||
return array_key_exists($name, $this->data);
|
||||
}
|
||||
|
||||
/** @return mixed[] */
|
||||
public function all(): array
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
public function toString(): string
|
||||
{
|
||||
return $this->encoded;
|
||||
}
|
||||
}
|
||||
25
vendor/lcobucci/jwt/src/Token/InvalidTokenStructure.php
vendored
Normal file
25
vendor/lcobucci/jwt/src/Token/InvalidTokenStructure.php
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Token;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use Lcobucci\JWT\Exception;
|
||||
|
||||
final class InvalidTokenStructure extends InvalidArgumentException implements Exception
|
||||
{
|
||||
public static function missingOrNotEnoughSeparators(): self
|
||||
{
|
||||
return new self('The JWT string must have two dots');
|
||||
}
|
||||
|
||||
public static function arrayExpected(string $part): self
|
||||
{
|
||||
return new self($part . ' must be an array');
|
||||
}
|
||||
|
||||
public static function dateIsNotParseable(string $value): self
|
||||
{
|
||||
return new self('Value is not in the allowed date format: ' . $value);
|
||||
}
|
||||
}
|
||||
154
vendor/lcobucci/jwt/src/Token/Parser.php
vendored
Normal file
154
vendor/lcobucci/jwt/src/Token/Parser.php
vendored
Normal file
@@ -0,0 +1,154 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Token;
|
||||
|
||||
use DateTimeImmutable;
|
||||
use Lcobucci\JWT\Decoder;
|
||||
use Lcobucci\JWT\Parser as ParserInterface;
|
||||
use Lcobucci\JWT\Token as TokenInterface;
|
||||
|
||||
use function array_key_exists;
|
||||
use function count;
|
||||
use function explode;
|
||||
use function is_array;
|
||||
use function is_numeric;
|
||||
use function number_format;
|
||||
|
||||
final class Parser implements ParserInterface
|
||||
{
|
||||
private const MICROSECOND_PRECISION = 6;
|
||||
|
||||
private Decoder $decoder;
|
||||
|
||||
public function __construct(Decoder $decoder)
|
||||
{
|
||||
$this->decoder = $decoder;
|
||||
}
|
||||
|
||||
public function parse(string $jwt): TokenInterface
|
||||
{
|
||||
[$encodedHeaders, $encodedClaims, $encodedSignature] = $this->splitJwt($jwt);
|
||||
|
||||
$header = $this->parseHeader($encodedHeaders);
|
||||
|
||||
return new Plain(
|
||||
new DataSet($header, $encodedHeaders),
|
||||
new DataSet($this->parseClaims($encodedClaims), $encodedClaims),
|
||||
$this->parseSignature($header, $encodedSignature)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits the JWT string into an array
|
||||
*
|
||||
* @return string[]
|
||||
*
|
||||
* @throws InvalidTokenStructure When JWT doesn't have all parts.
|
||||
*/
|
||||
private function splitJwt(string $jwt): array
|
||||
{
|
||||
$data = explode('.', $jwt);
|
||||
|
||||
if (count($data) !== 3) {
|
||||
throw InvalidTokenStructure::missingOrNotEnoughSeparators();
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the header from a string
|
||||
*
|
||||
* @return mixed[]
|
||||
*
|
||||
* @throws UnsupportedHeaderFound When an invalid header is informed.
|
||||
* @throws InvalidTokenStructure When parsed content isn't an array.
|
||||
*/
|
||||
private function parseHeader(string $data): array
|
||||
{
|
||||
$header = $this->decoder->jsonDecode($this->decoder->base64UrlDecode($data));
|
||||
|
||||
if (! is_array($header)) {
|
||||
throw InvalidTokenStructure::arrayExpected('headers');
|
||||
}
|
||||
|
||||
if (array_key_exists('enc', $header)) {
|
||||
throw UnsupportedHeaderFound::encryption();
|
||||
}
|
||||
|
||||
if (! array_key_exists('typ', $header)) {
|
||||
$header['typ'] = 'JWT';
|
||||
}
|
||||
|
||||
return $header;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the claim set from a string
|
||||
*
|
||||
* @return mixed[]
|
||||
*
|
||||
* @throws InvalidTokenStructure When parsed content isn't an array or contains non-parseable dates.
|
||||
*/
|
||||
private function parseClaims(string $data): array
|
||||
{
|
||||
$claims = $this->decoder->jsonDecode($this->decoder->base64UrlDecode($data));
|
||||
|
||||
if (! is_array($claims)) {
|
||||
throw InvalidTokenStructure::arrayExpected('claims');
|
||||
}
|
||||
|
||||
if (array_key_exists(RegisteredClaims::AUDIENCE, $claims)) {
|
||||
$claims[RegisteredClaims::AUDIENCE] = (array) $claims[RegisteredClaims::AUDIENCE];
|
||||
}
|
||||
|
||||
foreach (RegisteredClaims::DATE_CLAIMS as $claim) {
|
||||
if (! array_key_exists($claim, $claims)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$claims[$claim] = $this->convertDate($claims[$claim]);
|
||||
}
|
||||
|
||||
return $claims;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|float|string $timestamp
|
||||
*
|
||||
* @throws InvalidTokenStructure
|
||||
*/
|
||||
private function convertDate($timestamp): DateTimeImmutable
|
||||
{
|
||||
if (! is_numeric($timestamp)) {
|
||||
throw InvalidTokenStructure::dateIsNotParseable($timestamp);
|
||||
}
|
||||
|
||||
$normalizedTimestamp = number_format((float) $timestamp, self::MICROSECOND_PRECISION, '.', '');
|
||||
|
||||
$date = DateTimeImmutable::createFromFormat('U.u', $normalizedTimestamp);
|
||||
|
||||
if ($date === false) {
|
||||
throw InvalidTokenStructure::dateIsNotParseable($normalizedTimestamp);
|
||||
}
|
||||
|
||||
return $date;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the signature from given data
|
||||
*
|
||||
* @param mixed[] $header
|
||||
*/
|
||||
private function parseSignature(array $header, string $data): Signature
|
||||
{
|
||||
if ($data === '' || ! array_key_exists('alg', $header) || $header['alg'] === 'none') {
|
||||
return Signature::fromEmptyData();
|
||||
}
|
||||
|
||||
$hash = $this->decoder->base64UrlDecode($data);
|
||||
|
||||
return new Signature($hash, $data);
|
||||
}
|
||||
}
|
||||
92
vendor/lcobucci/jwt/src/Token/Plain.php
vendored
Normal file
92
vendor/lcobucci/jwt/src/Token/Plain.php
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Token;
|
||||
|
||||
use DateTimeInterface;
|
||||
use Lcobucci\JWT\Token as TokenInterface;
|
||||
|
||||
use function in_array;
|
||||
|
||||
final class Plain implements TokenInterface
|
||||
{
|
||||
private DataSet $headers;
|
||||
private DataSet $claims;
|
||||
private Signature $signature;
|
||||
|
||||
public function __construct(
|
||||
DataSet $headers,
|
||||
DataSet $claims,
|
||||
Signature $signature
|
||||
) {
|
||||
$this->headers = $headers;
|
||||
$this->claims = $claims;
|
||||
$this->signature = $signature;
|
||||
}
|
||||
|
||||
public function headers(): DataSet
|
||||
{
|
||||
return $this->headers;
|
||||
}
|
||||
|
||||
public function claims(): DataSet
|
||||
{
|
||||
return $this->claims;
|
||||
}
|
||||
|
||||
public function signature(): Signature
|
||||
{
|
||||
return $this->signature;
|
||||
}
|
||||
|
||||
public function payload(): string
|
||||
{
|
||||
return $this->headers->toString() . '.' . $this->claims->toString();
|
||||
}
|
||||
|
||||
public function isPermittedFor(string $audience): bool
|
||||
{
|
||||
return in_array($audience, $this->claims->get(RegisteredClaims::AUDIENCE, []), true);
|
||||
}
|
||||
|
||||
public function isIdentifiedBy(string $id): bool
|
||||
{
|
||||
return $this->claims->get(RegisteredClaims::ID) === $id;
|
||||
}
|
||||
|
||||
public function isRelatedTo(string $subject): bool
|
||||
{
|
||||
return $this->claims->get(RegisteredClaims::SUBJECT) === $subject;
|
||||
}
|
||||
|
||||
public function hasBeenIssuedBy(string ...$issuers): bool
|
||||
{
|
||||
return in_array($this->claims->get(RegisteredClaims::ISSUER), $issuers, true);
|
||||
}
|
||||
|
||||
public function hasBeenIssuedBefore(DateTimeInterface $now): bool
|
||||
{
|
||||
return $now >= $this->claims->get(RegisteredClaims::ISSUED_AT);
|
||||
}
|
||||
|
||||
public function isMinimumTimeBefore(DateTimeInterface $now): bool
|
||||
{
|
||||
return $now >= $this->claims->get(RegisteredClaims::NOT_BEFORE);
|
||||
}
|
||||
|
||||
public function isExpired(DateTimeInterface $now): bool
|
||||
{
|
||||
if (! $this->claims->has(RegisteredClaims::EXPIRATION_TIME)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $now >= $this->claims->get(RegisteredClaims::EXPIRATION_TIME);
|
||||
}
|
||||
|
||||
public function toString(): string
|
||||
{
|
||||
return $this->headers->toString() . '.'
|
||||
. $this->claims->toString() . '.'
|
||||
. $this->signature->toString();
|
||||
}
|
||||
}
|
||||
20
vendor/lcobucci/jwt/src/Token/RegisteredClaimGiven.php
vendored
Normal file
20
vendor/lcobucci/jwt/src/Token/RegisteredClaimGiven.php
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Token;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use Lcobucci\JWT\Exception;
|
||||
|
||||
use function sprintf;
|
||||
|
||||
final class RegisteredClaimGiven extends InvalidArgumentException implements Exception
|
||||
{
|
||||
private const DEFAULT_MESSAGE = 'Builder#withClaim() is meant to be used for non-registered claims, '
|
||||
. 'check the documentation on how to set claim "%s"';
|
||||
|
||||
public static function forClaim(string $name): self
|
||||
{
|
||||
return new self(sprintf(self::DEFAULT_MESSAGE, $name));
|
||||
}
|
||||
}
|
||||
77
vendor/lcobucci/jwt/src/Token/RegisteredClaims.php
vendored
Normal file
77
vendor/lcobucci/jwt/src/Token/RegisteredClaims.php
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Token;
|
||||
|
||||
/**
|
||||
* Defines the list of claims that are registered in the IANA "JSON Web Token Claims" registry
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc7519#section-4.1
|
||||
*/
|
||||
interface RegisteredClaims
|
||||
{
|
||||
public const ALL = [
|
||||
self::AUDIENCE,
|
||||
self::EXPIRATION_TIME,
|
||||
self::ID,
|
||||
self::ISSUED_AT,
|
||||
self::ISSUER,
|
||||
self::NOT_BEFORE,
|
||||
self::SUBJECT,
|
||||
];
|
||||
|
||||
public const DATE_CLAIMS = [
|
||||
self::ISSUED_AT,
|
||||
self::NOT_BEFORE,
|
||||
self::EXPIRATION_TIME,
|
||||
];
|
||||
|
||||
/**
|
||||
* Identifies the recipients that the JWT is intended for
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc7519#section-4.1.3
|
||||
*/
|
||||
public const AUDIENCE = 'aud';
|
||||
|
||||
/**
|
||||
* Identifies the expiration time on or after which the JWT MUST NOT be accepted for processing
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc7519#section-4.1.4
|
||||
*/
|
||||
public const EXPIRATION_TIME = 'exp';
|
||||
|
||||
/**
|
||||
* Provides a unique identifier for the JWT
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc7519#section-4.1.7
|
||||
*/
|
||||
public const ID = 'jti';
|
||||
|
||||
/**
|
||||
* Identifies the time at which the JWT was issued
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc7519#section-4.1.6
|
||||
*/
|
||||
public const ISSUED_AT = 'iat';
|
||||
|
||||
/**
|
||||
* Identifies the principal that issued the JWT
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc7519#section-4.1.1
|
||||
*/
|
||||
public const ISSUER = 'iss';
|
||||
|
||||
/**
|
||||
* Identifies the time before which the JWT MUST NOT be accepted for processing
|
||||
*
|
||||
* https://tools.ietf.org/html/rfc7519#section-4.1.5
|
||||
*/
|
||||
public const NOT_BEFORE = 'nbf';
|
||||
|
||||
/**
|
||||
* Identifies the principal that is the subject of the JWT.
|
||||
*
|
||||
* https://tools.ietf.org/html/rfc7519#section-4.1.2
|
||||
*/
|
||||
public const SUBJECT = 'sub';
|
||||
}
|
||||
34
vendor/lcobucci/jwt/src/Token/Signature.php
vendored
Normal file
34
vendor/lcobucci/jwt/src/Token/Signature.php
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Token;
|
||||
|
||||
final class Signature
|
||||
{
|
||||
private string $hash;
|
||||
private string $encoded;
|
||||
|
||||
public function __construct(string $hash, string $encoded)
|
||||
{
|
||||
$this->hash = $hash;
|
||||
$this->encoded = $encoded;
|
||||
}
|
||||
|
||||
public static function fromEmptyData(): self
|
||||
{
|
||||
return new self('', '');
|
||||
}
|
||||
|
||||
public function hash(): string
|
||||
{
|
||||
return $this->hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the encoded version of the signature
|
||||
*/
|
||||
public function toString(): string
|
||||
{
|
||||
return $this->encoded;
|
||||
}
|
||||
}
|
||||
15
vendor/lcobucci/jwt/src/Token/UnsupportedHeaderFound.php
vendored
Normal file
15
vendor/lcobucci/jwt/src/Token/UnsupportedHeaderFound.php
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Token;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use Lcobucci\JWT\Exception;
|
||||
|
||||
final class UnsupportedHeaderFound extends InvalidArgumentException implements Exception
|
||||
{
|
||||
public static function encryption(): self
|
||||
{
|
||||
return new self('Encryption is not supported yet');
|
||||
}
|
||||
}
|
||||
12
vendor/lcobucci/jwt/src/Validation/Constraint.php
vendored
Normal file
12
vendor/lcobucci/jwt/src/Validation/Constraint.php
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Validation;
|
||||
|
||||
use Lcobucci\JWT\Token;
|
||||
|
||||
interface Constraint
|
||||
{
|
||||
/** @throws ConstraintViolation */
|
||||
public function assert(Token $token): void;
|
||||
}
|
||||
27
vendor/lcobucci/jwt/src/Validation/Constraint/IdentifiedBy.php
vendored
Normal file
27
vendor/lcobucci/jwt/src/Validation/Constraint/IdentifiedBy.php
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Validation\Constraint;
|
||||
|
||||
use Lcobucci\JWT\Token;
|
||||
use Lcobucci\JWT\Validation\Constraint;
|
||||
use Lcobucci\JWT\Validation\ConstraintViolation;
|
||||
|
||||
final class IdentifiedBy implements Constraint
|
||||
{
|
||||
private string $id;
|
||||
|
||||
public function __construct(string $id)
|
||||
{
|
||||
$this->id = $id;
|
||||
}
|
||||
|
||||
public function assert(Token $token): void
|
||||
{
|
||||
if (! $token->isIdentifiedBy($this->id)) {
|
||||
throw new ConstraintViolation(
|
||||
'The token is not identified with the expected ID'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
28
vendor/lcobucci/jwt/src/Validation/Constraint/IssuedBy.php
vendored
Normal file
28
vendor/lcobucci/jwt/src/Validation/Constraint/IssuedBy.php
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Validation\Constraint;
|
||||
|
||||
use Lcobucci\JWT\Token;
|
||||
use Lcobucci\JWT\Validation\Constraint;
|
||||
use Lcobucci\JWT\Validation\ConstraintViolation;
|
||||
|
||||
final class IssuedBy implements Constraint
|
||||
{
|
||||
/** @var string[] */
|
||||
private array $issuers;
|
||||
|
||||
public function __construct(string ...$issuers)
|
||||
{
|
||||
$this->issuers = $issuers;
|
||||
}
|
||||
|
||||
public function assert(Token $token): void
|
||||
{
|
||||
if (! $token->hasBeenIssuedBy(...$this->issuers)) {
|
||||
throw new ConstraintViolation(
|
||||
'The token was not issued by the given issuers'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
15
vendor/lcobucci/jwt/src/Validation/Constraint/LeewayCannotBeNegative.php
vendored
Normal file
15
vendor/lcobucci/jwt/src/Validation/Constraint/LeewayCannotBeNegative.php
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Validation\Constraint;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use Lcobucci\JWT\Exception;
|
||||
|
||||
final class LeewayCannotBeNegative extends InvalidArgumentException implements Exception
|
||||
{
|
||||
public static function create(): self
|
||||
{
|
||||
return new self('Leeway cannot be negative');
|
||||
}
|
||||
}
|
||||
27
vendor/lcobucci/jwt/src/Validation/Constraint/PermittedFor.php
vendored
Normal file
27
vendor/lcobucci/jwt/src/Validation/Constraint/PermittedFor.php
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Validation\Constraint;
|
||||
|
||||
use Lcobucci\JWT\Token;
|
||||
use Lcobucci\JWT\Validation\Constraint;
|
||||
use Lcobucci\JWT\Validation\ConstraintViolation;
|
||||
|
||||
final class PermittedFor implements Constraint
|
||||
{
|
||||
private string $audience;
|
||||
|
||||
public function __construct(string $audience)
|
||||
{
|
||||
$this->audience = $audience;
|
||||
}
|
||||
|
||||
public function assert(Token $token): void
|
||||
{
|
||||
if (! $token->isPermittedFor($this->audience)) {
|
||||
throw new ConstraintViolation(
|
||||
'The token is not allowed to be used by this audience'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
27
vendor/lcobucci/jwt/src/Validation/Constraint/RelatedTo.php
vendored
Normal file
27
vendor/lcobucci/jwt/src/Validation/Constraint/RelatedTo.php
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Validation\Constraint;
|
||||
|
||||
use Lcobucci\JWT\Token;
|
||||
use Lcobucci\JWT\Validation\Constraint;
|
||||
use Lcobucci\JWT\Validation\ConstraintViolation;
|
||||
|
||||
final class RelatedTo implements Constraint
|
||||
{
|
||||
private string $subject;
|
||||
|
||||
public function __construct(string $subject)
|
||||
{
|
||||
$this->subject = $subject;
|
||||
}
|
||||
|
||||
public function assert(Token $token): void
|
||||
{
|
||||
if (! $token->isRelatedTo($this->subject)) {
|
||||
throw new ConstraintViolation(
|
||||
'The token is not related to the expected subject'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
36
vendor/lcobucci/jwt/src/Validation/Constraint/SignedWith.php
vendored
Normal file
36
vendor/lcobucci/jwt/src/Validation/Constraint/SignedWith.php
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Validation\Constraint;
|
||||
|
||||
use Lcobucci\JWT\Signer;
|
||||
use Lcobucci\JWT\Token;
|
||||
use Lcobucci\JWT\Validation\Constraint;
|
||||
use Lcobucci\JWT\Validation\ConstraintViolation;
|
||||
|
||||
final class SignedWith implements Constraint
|
||||
{
|
||||
private Signer $signer;
|
||||
private Signer\Key $key;
|
||||
|
||||
public function __construct(Signer $signer, Signer\Key $key)
|
||||
{
|
||||
$this->signer = $signer;
|
||||
$this->key = $key;
|
||||
}
|
||||
|
||||
public function assert(Token $token): void
|
||||
{
|
||||
if (! $token instanceof Token\Plain) {
|
||||
throw new ConstraintViolation('You should pass a plain token');
|
||||
}
|
||||
|
||||
if ($token->headers()->get('alg') !== $this->signer->algorithmId()) {
|
||||
throw new ConstraintViolation('Token signer mismatch');
|
||||
}
|
||||
|
||||
if (! $this->signer->verify($token->signature()->hash(), $token->payload(), $this->key)) {
|
||||
throw new ConstraintViolation('Token signature mismatch');
|
||||
}
|
||||
}
|
||||
}
|
||||
69
vendor/lcobucci/jwt/src/Validation/Constraint/ValidAt.php
vendored
Normal file
69
vendor/lcobucci/jwt/src/Validation/Constraint/ValidAt.php
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Validation\Constraint;
|
||||
|
||||
use DateInterval;
|
||||
use DateTimeInterface;
|
||||
use Lcobucci\Clock\Clock;
|
||||
use Lcobucci\JWT\Token;
|
||||
use Lcobucci\JWT\Validation\Constraint;
|
||||
use Lcobucci\JWT\Validation\ConstraintViolation;
|
||||
|
||||
final class ValidAt implements Constraint
|
||||
{
|
||||
private Clock $clock;
|
||||
private DateInterval $leeway;
|
||||
|
||||
public function __construct(Clock $clock, ?DateInterval $leeway = null)
|
||||
{
|
||||
$this->clock = $clock;
|
||||
$this->leeway = $this->guardLeeway($leeway);
|
||||
}
|
||||
|
||||
private function guardLeeway(?DateInterval $leeway): DateInterval
|
||||
{
|
||||
if ($leeway === null) {
|
||||
return new DateInterval('PT0S');
|
||||
}
|
||||
|
||||
if ($leeway->invert === 1) {
|
||||
throw LeewayCannotBeNegative::create();
|
||||
}
|
||||
|
||||
return $leeway;
|
||||
}
|
||||
|
||||
public function assert(Token $token): void
|
||||
{
|
||||
$now = $this->clock->now();
|
||||
|
||||
$this->assertIssueTime($token, $now->add($this->leeway));
|
||||
$this->assertMinimumTime($token, $now->add($this->leeway));
|
||||
$this->assertExpiration($token, $now->sub($this->leeway));
|
||||
}
|
||||
|
||||
/** @throws ConstraintViolation */
|
||||
private function assertExpiration(Token $token, DateTimeInterface $now): void
|
||||
{
|
||||
if ($token->isExpired($now)) {
|
||||
throw new ConstraintViolation('The token is expired');
|
||||
}
|
||||
}
|
||||
|
||||
/** @throws ConstraintViolation */
|
||||
private function assertMinimumTime(Token $token, DateTimeInterface $now): void
|
||||
{
|
||||
if (! $token->isMinimumTimeBefore($now)) {
|
||||
throw new ConstraintViolation('The token cannot be used yet');
|
||||
}
|
||||
}
|
||||
|
||||
/** @throws ConstraintViolation */
|
||||
private function assertIssueTime(Token $token, DateTimeInterface $now): void
|
||||
{
|
||||
if (! $token->hasBeenIssuedBefore($now)) {
|
||||
throw new ConstraintViolation('The token was issued in the future');
|
||||
}
|
||||
}
|
||||
}
|
||||
11
vendor/lcobucci/jwt/src/Validation/ConstraintViolation.php
vendored
Normal file
11
vendor/lcobucci/jwt/src/Validation/ConstraintViolation.php
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Validation;
|
||||
|
||||
use Lcobucci\JWT\Exception;
|
||||
use RuntimeException;
|
||||
|
||||
final class ConstraintViolation extends RuntimeException implements Exception
|
||||
{
|
||||
}
|
||||
11
vendor/lcobucci/jwt/src/Validation/NoConstraintsGiven.php
vendored
Normal file
11
vendor/lcobucci/jwt/src/Validation/NoConstraintsGiven.php
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Validation;
|
||||
|
||||
use Lcobucci\JWT\Exception;
|
||||
use RuntimeException;
|
||||
|
||||
final class NoConstraintsGiven extends RuntimeException implements Exception
|
||||
{
|
||||
}
|
||||
46
vendor/lcobucci/jwt/src/Validation/RequiredConstraintsViolated.php
vendored
Normal file
46
vendor/lcobucci/jwt/src/Validation/RequiredConstraintsViolated.php
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Validation;
|
||||
|
||||
use Lcobucci\JWT\Exception;
|
||||
use RuntimeException;
|
||||
|
||||
use function array_map;
|
||||
use function implode;
|
||||
|
||||
final class RequiredConstraintsViolated extends RuntimeException implements Exception
|
||||
{
|
||||
/** @var ConstraintViolation[] */
|
||||
private array $violations = [];
|
||||
|
||||
public static function fromViolations(ConstraintViolation ...$violations): self
|
||||
{
|
||||
$exception = new self(self::buildMessage($violations));
|
||||
$exception->violations = $violations;
|
||||
|
||||
return $exception;
|
||||
}
|
||||
|
||||
/** @param ConstraintViolation[] $violations */
|
||||
private static function buildMessage(array $violations): string
|
||||
{
|
||||
$violations = array_map(
|
||||
static function (ConstraintViolation $violation): string {
|
||||
return '- ' . $violation->getMessage();
|
||||
},
|
||||
$violations
|
||||
);
|
||||
|
||||
$message = "The token violates some mandatory constraints, details:\n";
|
||||
$message .= implode("\n", $violations);
|
||||
|
||||
return $message;
|
||||
}
|
||||
|
||||
/** @return ConstraintViolation[] */
|
||||
public function violations(): array
|
||||
{
|
||||
return $this->violations;
|
||||
}
|
||||
}
|
||||
56
vendor/lcobucci/jwt/src/Validation/Validator.php
vendored
Normal file
56
vendor/lcobucci/jwt/src/Validation/Validator.php
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT\Validation;
|
||||
|
||||
use Lcobucci\JWT\Token;
|
||||
|
||||
final class Validator implements \Lcobucci\JWT\Validator
|
||||
{
|
||||
public function assert(Token $token, Constraint ...$constraints): void
|
||||
{
|
||||
if ($constraints === []) {
|
||||
throw new NoConstraintsGiven('No constraint given.');
|
||||
}
|
||||
|
||||
$violations = [];
|
||||
|
||||
foreach ($constraints as $constraint) {
|
||||
$this->checkConstraint($constraint, $token, $violations);
|
||||
}
|
||||
|
||||
if ($violations) {
|
||||
throw RequiredConstraintsViolated::fromViolations(...$violations);
|
||||
}
|
||||
}
|
||||
|
||||
/** @param ConstraintViolation[] $violations */
|
||||
private function checkConstraint(
|
||||
Constraint $constraint,
|
||||
Token $token,
|
||||
array &$violations
|
||||
): void {
|
||||
try {
|
||||
$constraint->assert($token);
|
||||
} catch (ConstraintViolation $e) {
|
||||
$violations[] = $e;
|
||||
}
|
||||
}
|
||||
|
||||
public function validate(Token $token, Constraint ...$constraints): bool
|
||||
{
|
||||
if ($constraints === []) {
|
||||
throw new NoConstraintsGiven('No constraint given.');
|
||||
}
|
||||
|
||||
try {
|
||||
foreach ($constraints as $constraint) {
|
||||
$constraint->assert($token);
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (ConstraintViolation $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
20
vendor/lcobucci/jwt/src/Validator.php
vendored
Normal file
20
vendor/lcobucci/jwt/src/Validator.php
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lcobucci\JWT;
|
||||
|
||||
use Lcobucci\JWT\Validation\Constraint;
|
||||
use Lcobucci\JWT\Validation\NoConstraintsGiven;
|
||||
use Lcobucci\JWT\Validation\RequiredConstraintsViolated;
|
||||
|
||||
interface Validator
|
||||
{
|
||||
/**
|
||||
* @throws RequiredConstraintsViolated
|
||||
* @throws NoConstraintsGiven
|
||||
*/
|
||||
public function assert(Token $token, Constraint ...$constraints): void;
|
||||
|
||||
/** @throws NoConstraintsGiven */
|
||||
public function validate(Token $token, Constraint ...$constraints): bool;
|
||||
}
|
||||
Reference in New Issue
Block a user