Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backport new APIs #542

Merged
merged 17 commits into from
Nov 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions compat/lcobucci-clock-polyfill.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php

namespace Lcobucci\Clock;

use DateTimeImmutable;
use DateTimeZone;
use function interface_exists;

if (! interface_exists(Clock::class)) {
interface Clock
{
/** @return DateTimeImmutable */
public function now();
}

final class FrozenClock implements Clock
{
/** @var DateTimeImmutable */
private $now;

public function __construct(DateTimeImmutable $now)
{
$this->now = $now;
}

/** @return self */
public static function fromUTC()
{
return new self(new DateTimeImmutable('now', new DateTimeZone('UTC')));
}

public function setTo(DateTimeImmutable $now)
{
$this->now = $now;
}

public function now()
{
return $this->now;
}
}

final class SystemClock implements Clock
{
/** @var DateTimeZone */
private $timezone;

public function __construct(DateTimeZone $timezone)
{
$this->timezone = $timezone;
}

/** @return self */
public static function fromUTC()
{
return new self(new DateTimeZone('UTC'));
}

/** @return self */
public static function fromSystemTimezone()
{
return new self(new DateTimeZone(date_default_timezone_get()));
}

public function now()
{
return new DateTimeImmutable('now', $this->timezone);
}
}
}
6 changes: 5 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@
"Lcobucci\\JWT\\": "src"
},
"files": [
"compat/json-exception-polyfill.php"
"compat/json-exception-polyfill.php",
"compat/lcobucci-clock-polyfill.php"
]
},
"autoload-dev": {
Expand All @@ -44,6 +45,9 @@
]
}
},
"suggest": {
"lcobucci/clock": "*"
},
"extra": {
"branch-alias": {
"dev-master": "3.1-dev"
Expand Down
68 changes: 51 additions & 17 deletions src/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@

namespace Lcobucci\JWT;

use DateTimeImmutable;
use Lcobucci\JWT\Claim\Factory as ClaimFactory;
use Lcobucci\JWT\Parsing\Encoder;
use Lcobucci\JWT\Signer\Key;
use Lcobucci\JWT\Token\RegisteredClaimGiven;
use Lcobucci\JWT\Token\RegisteredClaims;

use function array_key_exists;
use function assert;
use function implode;
use function in_array;

Expand Down Expand Up @@ -124,14 +127,28 @@ public function setAudience($audience, $replicateAsHeader = false)
/**
* Configures the expiration time
*
* @param int $expiration
* @param int|DateTimeImmutable $expiration
* @param boolean $replicateAsHeader
*
* @return Builder
*/
public function expiresAt($expiration, $replicateAsHeader = false)
{
return $this->setRegisteredClaim('exp', (int) $expiration, $replicateAsHeader);
return $this->setRegisteredClaim('exp', $this->convertToDate($expiration), $replicateAsHeader);
}

/**
* @param int|DateTimeImmutable $value
*
* @return DateTimeImmutable
*/
private function convertToDate($value)
{
if (! $value instanceof DateTimeImmutable) {
return new DateTimeImmutable('@' . $value);
}

return $value;
}

/**
Expand All @@ -140,14 +157,14 @@ public function expiresAt($expiration, $replicateAsHeader = false)
* @deprecated This method will be removed on v4
* @see Builder::expiresAt()
*
* @param int $expiration
* @param int|DateTimeImmutable $expiration
* @param boolean $replicateAsHeader
*
* @return Builder
*/
public function setExpiration($expiration, $replicateAsHeader = false)
{
return $this->setRegisteredClaim('exp', (int) $expiration, $replicateAsHeader);
return $this->expiresAt($expiration, $replicateAsHeader);
}

/**
Expand Down Expand Up @@ -182,14 +199,14 @@ public function setId($id, $replicateAsHeader = false)
/**
* Configures the time that the token was issued
*
* @param int $issuedAt
* @param int|DateTimeImmutable $issuedAt
* @param boolean $replicateAsHeader
*
* @return Builder
*/
public function issuedAt($issuedAt, $replicateAsHeader = false)
{
return $this->setRegisteredClaim('iat', (int) $issuedAt, $replicateAsHeader);
return $this->setRegisteredClaim('iat', $this->convertToDate($issuedAt), $replicateAsHeader);
}

/**
Expand All @@ -198,7 +215,7 @@ public function issuedAt($issuedAt, $replicateAsHeader = false)
* @deprecated This method will be removed on v4
* @see Builder::issuedAt()
*
* @param int $issuedAt
* @param int|DateTimeImmutable $issuedAt
* @param boolean $replicateAsHeader
*
* @return Builder
Expand Down Expand Up @@ -240,14 +257,14 @@ public function setIssuer($issuer, $replicateAsHeader = false)
/**
* Configures the time before which the token cannot be accepted
*
* @param int $notBefore
* @param int|DateTimeImmutable $notBefore
* @param boolean $replicateAsHeader
*
* @return Builder
*/
public function canOnlyBeUsedAfter($notBefore, $replicateAsHeader = false)
{
return $this->setRegisteredClaim('nbf', (int) $notBefore, $replicateAsHeader);
return $this->setRegisteredClaim('nbf', $this->convertToDate($notBefore), $replicateAsHeader);
}

/**
Expand All @@ -256,7 +273,7 @@ public function canOnlyBeUsedAfter($notBefore, $replicateAsHeader = false)
* @deprecated This method will be removed on v4
* @see Builder::canOnlyBeUsedAfter()
*
* @param int $notBefore
* @param int|DateTimeImmutable $notBefore
* @param boolean $replicateAsHeader
*
* @return Builder
Expand Down Expand Up @@ -309,7 +326,7 @@ protected function setRegisteredClaim($name, $value, $replicate)
$this->configureClaim($name, $value);

if ($replicate) {
$this->headers[$name] = $this->claims[$name];
$this->headers[$name] = $value;
}

return $this;
Expand All @@ -325,7 +342,7 @@ protected function setRegisteredClaim($name, $value, $replicate)
*/
public function withHeader($name, $value)
{
$this->headers[(string) $name] = $this->claimFactory->create($name, $value);
$this->headers[(string) $name] = $value;

return $this;
}
Expand Down Expand Up @@ -370,8 +387,7 @@ public function with($name, $value)
*/
private function configureClaim($name, $value)
{
$name = (string) $name;
$this->claims[$name] = $this->claimFactory->create($name, $value);
$this->claims[(string) $name] = $value;

return $this;
}
Expand Down Expand Up @@ -465,8 +481,8 @@ public function getToken(Signer $signer = null, Key $key = null)
}

$payload = [
$this->encoder->base64UrlEncode($this->encoder->jsonEncode($this->headers)),
$this->encoder->base64UrlEncode($this->encoder->jsonEncode($this->claims))
$this->encoder->base64UrlEncode($this->encoder->jsonEncode($this->convertDatesToInt($this->headers))),
$this->encoder->base64UrlEncode($this->encoder->jsonEncode($this->convertDatesToInt($this->claims)))
];

$signature = $this->createSignature($payload, $signer, $key);
Expand All @@ -475,7 +491,25 @@ public function getToken(Signer $signer = null, Key $key = null)
$payload[] = $this->encoder->base64UrlEncode($signature);
}

return new Token($this->headers, $this->claims, $signature, $payload);
return new Token($this->headers, $this->claims, $signature, $payload, $this->claimFactory);
}

/**
* @param array<string, mixed> $items
*
* @return array<string, mixed>
*/
private function convertDatesToInt(array $items)
{
foreach (RegisteredClaims::DATE_CLAIMS as $name) {
if (! array_key_exists($name, $items) || ! $items[$name] instanceof DateTimeImmutable) {
continue;
}

$items[$name] = $items[$name]->getTimestamp();
}

return $items;
}

/**
Expand Down
7 changes: 7 additions & 0 deletions src/Claim/Factory.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@

namespace Lcobucci\JWT\Claim;

use DateTimeImmutable;
use Lcobucci\JWT\Claim;
use Lcobucci\JWT\Token\RegisteredClaims;
use function in_array;

/**
* Class that create claims
Expand Down Expand Up @@ -57,6 +60,10 @@ public function __construct(array $callbacks = [])
*/
public function create($name, $value)
{
if ($value instanceof DateTimeImmutable && in_array($name, RegisteredClaims::DATE_CLAIMS, true)) {
$value = $value->getTimestamp();
}

if (!empty($this->callbacks[$name])) {
return call_user_func($this->callbacks[$name], $name, $value);
}
Expand Down
Loading