-
-
Notifications
You must be signed in to change notification settings - Fork 601
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
Create new validation API #129
Changes from all commits
75fbfee
b3d246f
d90447e
5dd0976
bc5eea2
29c3aa1
bdc15ce
3d8d343
1ef2a86
3ad8661
4fb4d79
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,3 +2,4 @@ vendor | |
phpunit.xml | ||
composer.lock | ||
humbuglog.txt | ||
coverage |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -41,6 +41,7 @@ | |
"autoload-dev": { | ||
"psr-4": { | ||
"Lcobucci\\JWT\\": [ | ||
"test/_keys", | ||
"test/unit", | ||
"test/functional" | ||
] | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,278 +10,71 @@ | |
namespace Lcobucci\JWT; | ||
|
||
use BadMethodCallException; | ||
use Lcobucci\Jose\Parsing; | ||
use Lcobucci\JWT\Claim\Factory as ClaimFactory; | ||
use Lcobucci\JWT\Signer\Key; | ||
use Lcobucci\JWT\Token\Plain; | ||
|
||
/** | ||
* This class makes easier the token creation process | ||
* | ||
* @author Luís Otávio Cobucci Oblonczyk <[email protected]> | ||
* @since 0.1.0 | ||
* @since 4.0.0 | ||
*/ | ||
class Builder | ||
interface 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 Parsing\Encoder | ||
*/ | ||
private $encoder; | ||
|
||
/** | ||
* The factory of claims | ||
* | ||
* @var ClaimFactory | ||
*/ | ||
private $claimFactory; | ||
|
||
/** | ||
* Initializes a new builder | ||
* | ||
* @param Parsing\Encoder $encoder | ||
* @param ClaimFactory $claimFactory | ||
* Appends a new audience | ||
*/ | ||
public function __construct( | ||
Parsing\Encoder $encoder, | ||
ClaimFactory $claimFactory | ||
) { | ||
$this->encoder = $encoder; | ||
$this->claimFactory = $claimFactory; | ||
$this->headers = ['typ'=> 'JWT', 'alg' => 'none']; | ||
$this->claims = []; | ||
} | ||
|
||
/** | ||
* Configures the audience | ||
* | ||
* @param string|array $audience | ||
* @param bool $addHeader | ||
* | ||
* @return Builder | ||
*/ | ||
public function canOnlyBeUsedBy(string $audience, bool $addHeader = false): Builder | ||
{ | ||
$audiences = isset($this->claims['aud']) | ||
? array_merge($this->claims['aud']->getValue(), [$audience]) | ||
: [$audience]; | ||
|
||
return $this->setRegisteredClaim( | ||
'aud', | ||
array_values(array_map('strval', $audiences)), | ||
$addHeader | ||
); | ||
} | ||
public function canOnlyBeUsedBy(string $audience, bool $addHeader = false): Builder; | ||
|
||
/** | ||
* Configures the expiration time | ||
* | ||
* @param int $expiration | ||
* @param bool $addHeader | ||
* | ||
* @return Builder | ||
*/ | ||
public function expiresAt(int $expiration, bool $addHeader = false): Builder | ||
{ | ||
return $this->setRegisteredClaim('exp', $expiration, $addHeader); | ||
} | ||
public function expiresAt(int $expiration, bool $addHeader = false): Builder; | ||
|
||
/** | ||
* Configures the token id | ||
* | ||
* @param string $id | ||
* @param boolean $addHeader | ||
* | ||
* @return Builder | ||
*/ | ||
public function identifiedBy(string $id, bool $addHeader = false): Builder | ||
{ | ||
return $this->setRegisteredClaim('jti', $id, $addHeader); | ||
} | ||
public function identifiedBy(string $id, bool $addHeader = false): Builder; | ||
|
||
/** | ||
* Configures the time that the token was issued | ||
* | ||
* @param int $issuedAt | ||
* @param bool $addHeader | ||
* | ||
* @return Builder | ||
*/ | ||
public function issuedAt(int $issuedAt, bool $addHeader = false): Builder | ||
{ | ||
return $this->setRegisteredClaim('iat', (int) $issuedAt, $addHeader); | ||
} | ||
public function issuedAt(int $issuedAt, bool $addHeader = false): Builder; | ||
|
||
/** | ||
* Configures the issuer | ||
* | ||
* @param string $issuer | ||
* @param bool $addHeader | ||
* | ||
* @return Builder | ||
*/ | ||
public function issuedBy(string $issuer, bool $addHeader = false): Builder | ||
{ | ||
return $this->setRegisteredClaim('iss', $issuer, $addHeader); | ||
} | ||
public function issuedBy(string $issuer, bool $addHeader = false): Builder; | ||
|
||
/** | ||
* Configures the time before which the token cannot be accepted | ||
* | ||
* @param int $notBefore | ||
* @param bool $addHeader | ||
* | ||
* @return Builder | ||
*/ | ||
public function canOnlyBeUsedAfter(int $notBefore, bool $addHeader = false): Builder | ||
{ | ||
return $this->setRegisteredClaim('nbf', $notBefore, $addHeader); | ||
} | ||
public function canOnlyBeUsedAfter(int $notBefore, bool $addHeader = false): Builder; | ||
|
||
/** | ||
* Configures the subject | ||
* | ||
* @param string $subject | ||
* @param bool $addHeader | ||
* | ||
* @return Builder | ||
*/ | ||
public function relatedTo(string $subject, bool $addHeader = false): Builder | ||
{ | ||
return $this->setRegisteredClaim('sub', $subject, $addHeader); | ||
} | ||
|
||
/** | ||
* Configures a registed claim | ||
* | ||
* @param string $name | ||
* @param mixed $value | ||
* @param bool $addHeader | ||
* | ||
* @return Builder | ||
*/ | ||
protected function setRegisteredClaim(string $name, $value, bool $addHeader): Builder | ||
{ | ||
$this->with($name, $value); | ||
|
||
if ($addHeader) { | ||
$this->headers[$name] = $this->claims[$name]; | ||
} | ||
|
||
return $this; | ||
} | ||
public function relatedTo(string $subject, bool $addHeader = false): Builder; | ||
|
||
/** | ||
* Configures a header item | ||
* | ||
* @param string $name | ||
* @param mixed $value | ||
* | ||
* @return Builder | ||
* | ||
* @throws BadMethodCallException When data has been already signed | ||
*/ | ||
public function withHeader(string $name, $value): Builder | ||
{ | ||
if ($this->signature) { | ||
throw new BadMethodCallException('You must unsign before make changes'); | ||
} | ||
|
||
$this->headers[$name] = $this->claimFactory->create($name, $value); | ||
|
||
return $this; | ||
} | ||
public function withHeader(string $name, $value): Builder; | ||
|
||
/** | ||
* Configures a claim item | ||
* | ||
* @param string $name | ||
* @param mixed $value | ||
* | ||
* @return Builder | ||
* | ||
* @throws BadMethodCallException When data has been already signed | ||
*/ | ||
public function with(string $name, $value): Builder | ||
{ | ||
if ($this->signature) { | ||
throw new BadMethodCallException('You must unsign before making changes'); | ||
} | ||
|
||
$this->claims[$name] = $this->claimFactory->create($name, $value); | ||
|
||
return $this; | ||
} | ||
|
||
/** | ||
* Signs the data | ||
* | ||
* @param Signer $signer | ||
* @param Key $key | ||
* | ||
* @return Builder | ||
*/ | ||
public function sign(Signer $signer, Key $key): Builder | ||
{ | ||
$signer->modifyHeader($this->headers); | ||
|
||
$this->signature = $signer->sign( | ||
$this->getToken()->getPayload(), | ||
$key | ||
); | ||
|
||
return $this; | ||
} | ||
public function with(string $name, $value): Builder; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Only There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Indeed, change needed There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
||
/** | ||
* Removes the signature from the builder | ||
* | ||
* @return Builder | ||
* Returns a signed token to be used | ||
*/ | ||
public function unsign(): Builder | ||
{ | ||
$this->signature = null; | ||
|
||
return $this; | ||
} | ||
public function getToken(Signer $signer, Key $key): Plain; | ||
|
||
/** | ||
* Returns the resultant token | ||
* | ||
* @return Token | ||
* Returns an unsecured token (not recommended) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wouldn't it make more sense to use the previous API with a no-op signer? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What you mean here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Have always a token, let a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's a good idea, it would simplify things indeed. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But it can be done in a different PR... I really want to have this merged instead of adding things to the stack There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. #152 is there for that. |
||
*/ | ||
public function getToken(): Token | ||
{ | ||
$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((string) $this->signature); | ||
} | ||
|
||
return new Token($this->headers, $this->claims, $this->signature, $payload); | ||
} | ||
public function getUnsecuredToken(): Plain; | ||
} |
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
belongsTo
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not really,
audience
is about who can consume the token.I wouldn't change it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Docblock specifies "appends", method name suggests "only". :confus:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Those names were defined on #113 we're just extracting an interface. Let's define on #150 and change them on a different PR.