<?php
declare(strict_types=1);
namespace ParagonIE\Paseto;
use ParagonIE\Paseto\Exception\{
EncodingException,
NotFoundException,
PasetoException
};
use ParagonIE\Paseto\Traits\RegisteredClaims;
/**
* Class JsonToken
* @package ParagonIE\Paseto
*/
class JsonToken
{
use RegisteredClaims;
/** @var array<string, string> */
protected $claims = [];
/** @var string $footer */
protected $footer = '';
/**
* @param Builder $builder
*
* @return Builder
*/
public function build(Builder $builder): Builder
{
return $builder->setJsonToken($this);
}
/**
* Get any arbitrary claim.
*
* @param string $claim
* @return mixed
* @throws PasetoException
*/
public function get(string $claim)
{
if (\array_key_exists($claim, $this->claims)) {
return $this->claims[$claim];
}
throw new NotFoundException('Claim not found: ' . $claim);
}
/**
* Get the 'aud' claim.
*
* @return string
* @throws PasetoException
*/
public function getAudience(): string
{
return (string) $this->get('aud');
}
/**
* Get all of the claims stored in this Paseto.
*
* @return array
*/
public function getClaims(): array
{
return $this->claims;
}
/**
* Get the 'exp' claim.
*
* @return \DateTime
* @throws PasetoException
*/
public function getExpiration(): \DateTime
{
return new \DateTime((string) $this->get('exp'));
}
/**
* Get the footer as a string.
*
* @return string
*/
public function getFooter(): string
{
return $this->footer;
}
/**
* Get the footer as an array. Assumes JSON.
*
* @return array
* @throws PasetoException
*/
public function getFooterArray(): array
{
/** @var array|bool $decoded */
$decoded = \json_decode($this->footer, true);
if (!\is_array($decoded)) {
throw new EncodingException('Footer is not a valid JSON document');
}
return $decoded;
}
/**
* Get the 'iat' claim.
*
* @return \DateTime
* @throws PasetoException
*/
public function getIssuedAt(): \DateTime
{
return new \DateTime((string) $this->get('iat'));
}
/**
* Get the 'iss' claim.
*
* @return string
* @throws PasetoException
*/
public function getIssuer(): string
{
return (string) $this->get('iss');
}
/**
* Get the 'jti' claim.
*
* @return string
* @throws PasetoException
*/
public function getJti(): string
{
return (string) $this->get('jti');
}
/**
* Get the 'nbf' claim.
*
* @return \DateTime
* @throws PasetoException
*/
public function getNotBefore(): \DateTime
{
return new \DateTime((string) $this->get('nbf'));
}
/**
* Get the 'sub' claim.
*
* @return string
* @throws PasetoException
*/
public function getSubject(): string
{
return (string) $this->get('sub');
}
/**
* Set a claim to an arbitrary value.
*
* @param string $claim
* @param string $value
* @return self
*/
public function set(string $claim, $value): self
{
$this->claims[$claim] = $value;
return $this;
}
/**
* Set the 'aud' claim.
*
* @param string $aud
* @return self
*/
public function setAudience(string $aud): self
{
$this->claims['aud'] = $aud;
return $this;
}
/**
* Set an array of claims in one go.
*
* @param array<string, string> $claims
* @return self
*/
public function setClaims(array $claims): self
{
$this->claims = $claims + $this->claims;
return $this;
}
/**
* Set the 'exp' claim.
*
* @param \DateTimeInterface|null $time
* @return self
*/
public function setExpiration(\DateTimeInterface $time = null): self
{
if (!$time) {
$time = new \DateTime('NOW');
}
$this->claims['exp'] = $time->format(\DateTime::ATOM);
return $this;
}
/**
* Set the footer.
*
* @param string $footer
* @return self
*/
public function setFooter(string $footer = ''): self
{
$this->footer = $footer;
return $this;
}
/**
* Set the footer, given an array of data. Converts to JSON.
*
* @param array $footer
* @return self
* @throws PasetoException
*/
public function setFooterArray(array $footer = []): self
{
$encoded = \json_encode($footer);
if (!\is_string($encoded)) {
throw new EncodingException('Could not encode array into JSON');
}
return $this->setFooter($encoded);
}
/**
* Set the 'iat' claim.
*
* @param \DateTimeInterface|null $time
* @return self
*/
public function setIssuedAt(\DateTimeInterface $time = null): self
{
if (!$time) {
$time = new \DateTime('NOW');
}
$this->claims['iat'] = $time->format(\DateTime::ATOM);
return $this;
}
/**
* Set the 'iss' claim.
*
* @param string $iss
* @return self
*/
public function setIssuer(string $iss): self
{
$this->claims['iss'] = $iss;
return $this;
}
/**
* Set the 'jti' claim.
*
* @param string $id
* @return self
*/
public function setJti(string $id): self
{
$this->claims['jti'] = $id;
return $this;
}
/**
* Set the 'nbf' claim.
*
* @param \DateTimeInterface|null $time
* @return self
*/
public function setNotBefore(\DateTimeInterface $time = null): self
{
if (!$time) {
$time = new \DateTime('NOW');
}
$this->claims['nbf'] = $time->format(\DateTime::ATOM);
return $this;
}
/**
* Set the 'sub' claim.
*
* @param string $sub
* @return self
*/
public function setSubject(string $sub): self
{
$this->claims['sub'] = $sub;
return $this;
}
/**
* Return a new JsonToken instance with a changed claim.
*
* @param string $claim
* @param string $value
* @return self
*/
public function with(string $claim, $value): self
{
return (clone $this)->set($claim, $value);
}
/**
* Return a new JsonToken instance with a changed 'aud' claim.
*
* @param string $aud
* @return self
*/
public function withAudience(string $aud): self
{
return (clone $this)->setAudience($aud);
}
/**
* Return a new JsonToken instance with an array of changed claims.
*
* @param array<string, string> $claims
* @return self
*/
public function withClaims(array $claims): self
{
return (clone $this)->setClaims($claims);
}
/**
* Return a new JsonToken instance with a changed 'exp' claim.
*
* @param \DateTimeInterface|null $time
* @return self
*/
public function withExpiration(\DateTimeInterface $time = null): self
{
return (clone $this)->setExpiration($time);
}
/**
* Return a new JsonToken instance with a changed footer.
*
* @param string $footer
* @return self
*/
public function withFooter(string $footer = ''): self
{
return (clone $this)->setFooter($footer);
}
/**
* Return a new JsonToken instance with a changed footer,
* representing the JSON-encoded array provided.
*
* @param array $footer
* @return self
* @throws PasetoException
*/
public function withFooterArray(array $footer = []): self
{
return (clone $this)->setFooterArray($footer);
}
/**
* Return a new JsonToken instance with a changed 'iat' claim.
*
* @param \DateTimeInterface|null $time
* @return self
*/
public function withIssuedAt(\DateTimeInterface $time = null): self
{
return (clone $this)->setIssuedAt($time);
}
/**
* Return a new JsonToken instance with a changed 'iss' claim.
*
* @param string $iss
* @return self
*/
public function withIssuer(string $iss): self
{
return (clone $this)->setIssuer($iss);
}
/**
* Return a new JsonToken instance with a changed 'jti' claim.
*
* @param string $id
* @return self
*/
public function withJti(string $id): self
{
return (clone $this)->setJti($id);
}
/**
* Return a new JsonToken instance with a changed 'nbf' claim.
*
* @param \DateTimeInterface|null $time
* @return self
*/
public function withNotBefore(\DateTimeInterface $time = null): self
{
return (clone $this)->setNotBefore($time);
}
/**
* Return a new JsonToken instance with a changed 'sub' claim.
*
* @param string $sub
* @return self
*/
public function withSubject(string $sub): self
{
return (clone $this)->setSubject($sub);
}
}
|