* @since 0.1.0 */ class Builder { /** * The token header * * @var array */ private $headers; /** * The token claim set * * @var array */ private $claims; /** * The token signature * * @var Signature */ private $signature; /** * The data encoder * * @var Encoder */ private $encoder; /** * The factory of claims * * @var ClaimFactory */ private $claimFactory; /** * Initializes a new builder * * @param Encoder $encoder * @param ClaimFactory $claimFactory */ public function __construct( Encoder $encoder = null, ClaimFactory $claimFactory = null ) { $this->encoder = $encoder ?: new Encoder(); $this->claimFactory = $claimFactory ?: new ClaimFactory(); $this->headers = ['typ'=> 'JWT', 'alg' => 'none']; $this->claims = []; } /** * Configures the audience * * @param string $audience * @param boolean $replicateAsHeader * * @return Builder */ public function setAudience($audience, $replicateAsHeader = false) { return $this->setRegisteredClaim('aud', (string) $audience, $replicateAsHeader); } /** * Configures the expiration time * * @param int $expiration * @param boolean $replicateAsHeader * * @return Builder */ public function setExpiration($expiration, $replicateAsHeader = false) { return $this->setRegisteredClaim('exp', (int) $expiration, $replicateAsHeader); } /** * Configures the token id * * @param string $id * @param boolean $replicateAsHeader * * @return Builder */ public function setId($id, $replicateAsHeader = false) { return $this->setRegisteredClaim('jti', (string) $id, $replicateAsHeader); } /** * Configures the time that the token was issued * * @param int $issuedAt * @param boolean $replicateAsHeader * * @return Builder */ public function setIssuedAt($issuedAt, $replicateAsHeader = false) { return $this->setRegisteredClaim('iat', (int) $issuedAt, $replicateAsHeader); } /** * Configures the issuer * * @param string $issuer * @param boolean $replicateAsHeader * * @return Builder */ public function setIssuer($issuer, $replicateAsHeader = false) { return $this->setRegisteredClaim('iss', (string) $issuer, $replicateAsHeader); } /** * Configures the time before which the token cannot be accepted * * @param int $notBefore * @param boolean $replicateAsHeader * * @return Builder */ public function setNotBefore($notBefore, $replicateAsHeader = false) { return $this->setRegisteredClaim('nbf', (int) $notBefore, $replicateAsHeader); } /** * Configures the subject * * @param string $subject * @param boolean $replicateAsHeader * * @return Builder */ public function setSubject($subject, $replicateAsHeader = false) { return $this->setRegisteredClaim('sub', (string) $subject, $replicateAsHeader); } /** * Configures a registed claim * * @param string $name * @param mixed $value * @param boolean $replicate * * @return Builder */ protected function setRegisteredClaim($name, $value, $replicate) { $this->set($name, $value); if ($replicate) { $this->headers[$name] = $this->claims[$name]; } return $this; } /** * Configures a header item * * @param string $name * @param mixed $value * * @return Builder * * @throws BadMethodCallException When data has been already signed */ public function setHeader($name, $value) { if ($this->signature) { throw new BadMethodCallException('You must unsign before make changes'); } $this->headers[(string) $name] = $this->claimFactory->create($name, $value); return $this; } /** * Configures a claim item * * @param string $name * @param mixed $value * * @return Builder * * @throws BadMethodCallException When data has been already signed */ public function set($name, $value) { if ($this->signature) { throw new BadMethodCallException('You must unsign before making changes'); } $this->claims[(string) $name] = $this->claimFactory->create($name, $value); return $this; } /** * Signs the data * * @param Signer $signer * @param string $key * * @return Builder */ public function sign(Signer $signer, $key) { $signer->modifyHeader($this->headers); $this->signature = $signer->sign( $this->getToken()->getPayload(), $key ); return $this; } /** * Removes the signature from the builder * * @return Builder */ public function unsign() { $this->signature = null; return $this; } /** * Returns the resultant token * * @return Token */ public function getToken() { $payload = [ $this->encoder->base64UrlEncode($this->encoder->jsonEncode($this->headers)), $this->encoder->base64UrlEncode($this->encoder->jsonEncode($this->claims)) ]; if ($this->signature !== null) { $payload[] = $this->encoder->base64UrlEncode($this->signature); } return new Token($this->headers, $this->claims, $this->signature, $payload); } }