Skip to content

Commit

Permalink
Create the signature when retrieving the token
Browse files Browse the repository at this point in the history
  • Loading branch information
lcobucci committed Nov 7, 2016
1 parent e0ca0a8 commit 3eed588
Show file tree
Hide file tree
Showing 12 changed files with 156 additions and 279 deletions.
13 changes: 4 additions & 9 deletions src/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,17 +69,12 @@ public function withHeader(string $name, $value): Builder;
public function with(string $name, $value): Builder;

/**
* Signs the data
* Returns a signed token to be used
*/
public function sign(Signer $signer, Key $key): Builder;
public function getToken(Signer $signer, Key $key): Token;

/**
* Removes the signature from the builder
* Returns an unsecured token (not recommended)
*/
public function unsign(): Builder;

/**
* Returns the resultant token
*/
public function getToken(): Token;
public function getUnsecuredToken(): Token;
}
74 changes: 18 additions & 56 deletions src/Storage/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,6 @@ final class Builder implements BuilderInterface
*/
private $claims = [];

/**
* The token signature
*
* @var string|null
*/
private $signature;

/**
* The data encoder
*
Expand Down Expand Up @@ -142,10 +135,6 @@ private function setRegisteredClaim(string $name, $value, bool $addHeader): Buil
*/
public function withHeader(string $name, $value): BuilderInterface
{
if ($this->signature !== null) {
throw new BadMethodCallException('You must unsign before make changes');
}

$this->headers[$name] = $value;

return $this;
Expand All @@ -156,74 +145,47 @@ public function withHeader(string $name, $value): BuilderInterface
*/
public function with(string $name, $value): BuilderInterface
{
if ($this->signature !== null) {
throw new BadMethodCallException('You must unsign before making changes');
}

$this->claims[$name] = $value;

return $this;
}

/**
* {@inheritdoc}
*/
public function sign(Signer $signer, Key $key): BuilderInterface
private function encode(array $items): string
{
$this->headers['alg'] = $signer->getAlgorithmId();

$this->signature = $signer->sign(
$this->getToken()->payload(),
$key
return $this->encoder->base64UrlEncode(
$this->encoder->jsonEncode($items)
);

return $this;
}

/**
* {@inheritdoc}
*/
public function unsign(): BuilderInterface
public function getToken(Signer $signer, Key $key): TokenInterface
{
$this->headers['alg'] = 'none';
$this->signature = null;
$headers = $this->headers;
$headers['alg'] = $signer->getAlgorithmId();

return $this;
}
$encodedHeaders = $this->encode($headers);
$encodedClaims = $this->encode($this->claims);

private function encodeHeaders(): string
{
return $this->encoder->base64UrlEncode(
$this->encoder->jsonEncode($this->headers)
);
}
$signature = $signer->sign($encodedHeaders . '.' . $encodedClaims, $key);
$encodedSignature = $this->encoder->base64UrlEncode($signature);

private function encodeClaims(): string
{
return $this->encoder->base64UrlEncode(
$this->encoder->jsonEncode($this->claims)
return Token::signed(
new DataSet($headers, $encodedHeaders),
new DataSet($this->claims, $encodedClaims),
new Signature($signature, $encodedSignature)
);
}

/**
* {@inheritdoc}
*/
public function getToken(): TokenInterface
public function getUnsecuredToken(): TokenInterface
{
$headers = new DataSet($this->headers, $this->encodeHeaders());
$claims = new DataSet($this->claims, $this->encodeClaims());

if ($this->signature === null) {
return new Token($headers, $claims);
}

return new Token(
$headers,
$claims,
new Signature(
$this->signature,
$this->encoder->base64UrlEncode($this->signature)
)
return Token::unsecured(
new DataSet($this->headers, $this->encode($this->headers)),
new DataSet($this->claims, $this->encode($this->claims))
);
}
}
22 changes: 17 additions & 5 deletions src/Storage/Parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,23 @@ public function parse(string $jwt): TokenInterface
}
}

return new Token(
new DataSet($header, $data[0]),
new DataSet($claims, $data[1]),
$signature
);
return $this->createToken($header, $claims, $data, $signature);
}

private function createToken(
array $headers,
array $claims,
array $encodedData,
Signature $signature = null
): Token {
$headers = new DataSet($headers, $encodedData[0]);
$claims = new DataSet($claims, $encodedData[1]);

if ($signature) {
return Token::signed($headers, $claims, $signature);
}

return Token::unsecured($headers, $claims);
}

/**
Expand Down
22 changes: 14 additions & 8 deletions src/Storage/Token.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,20 @@ final class Token implements TokenInterface
*/
private $signature;

/**
* Initializes the object
*
* @param DataSet $headers
* @param DataSet $claims
* @param Signature|null $signature
*/
public function __construct(
public static function unsecured(DataSet $headers, DataSet $claims): self
{
return new self($headers, $claims);
}

public static function signed(
DataSet $headers,
DataSet $claims,
Signature $signature
): self {
return new self($headers, $claims, $signature);
}

private function __construct(
DataSet $headers,
DataSet $claims,
Signature $signature = null
Expand Down
10 changes: 4 additions & 6 deletions test/functional/EcdsaTokenTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public function builderShouldRaiseExceptionWhenKeyIsInvalid()
->canOnlyBeUsedBy('http://client.abc.com')
->issuedBy('http://api.abc.com')
->with('user', ['name' => 'testing', 'email' => '[email protected]'])
->sign($this->config->getSigner(), new Key('testing'));
->getToken($this->config->getSigner(), new Key('testing'));
}

/**
Expand Down Expand Up @@ -93,7 +93,7 @@ public function builderShouldRaiseExceptionWhenKeyIsNotEcdsaCompatible()
->canOnlyBeUsedBy('http://client.abc.com')
->issuedBy('http://api.abc.com')
->with('user', ['name' => 'testing', 'email' => '[email protected]'])
->sign($this->config->getSigner(), static::$rsaKeys['private']);
->getToken($this->config->getSigner(), static::$rsaKeys['private']);
}

/**
Expand Down Expand Up @@ -122,8 +122,7 @@ public function builderCanGenerateAToken()
->issuedBy('http://api.abc.com')
->with('user', $user)
->withHeader('jki', '1234')
->sign($this->config->getSigner(), static::$ecdsaKeys['private'])
->getToken();
->getToken($this->config->getSigner(), static::$ecdsaKeys['private']);

self::assertAttributeInstanceOf(Signature::class, 'signature', $token);
self::assertEquals('1234', $token->headers()->get('jki'));
Expand Down Expand Up @@ -317,8 +316,7 @@ public function everythingShouldWorkWithAKeyWithParams()
->issuedBy('http://api.abc.com')
->with('user', ['name' => 'testing', 'email' => '[email protected]'])
->withHeader('jki', '1234')
->sign($signer, static::$ecdsaKeys['private-params'])
->getToken();
->getToken($signer, static::$ecdsaKeys['private-params']);

$constraint = new SignedWith(
$this->config->getSigner(),
Expand Down
4 changes: 1 addition & 3 deletions test/functional/HmacTokenTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
namespace Lcobucci\JWT\FunctionalTests;

use Lcobucci\JWT\Configuration;
use Lcobucci\JWT\Signer;
use Lcobucci\JWT\Signer\Hmac\Sha512;
use Lcobucci\JWT\Signer\Key;
use Lcobucci\JWT\Storage\Signature;
Expand Down Expand Up @@ -58,8 +57,7 @@ public function builderCanGenerateAToken()
->issuedBy('http://api.abc.com')
->with('user', $user)
->withHeader('jki', '1234')
->sign($this->config->getSigner(), new Key('testing'))
->getToken();
->getToken($this->config->getSigner(), new Key('testing'));

self::assertAttributeInstanceOf(Signature::class, 'signature', $token);
self::assertEquals('1234', $token->headers()->get('jki'));
Expand Down
8 changes: 3 additions & 5 deletions test/functional/RsaTokenTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@

use Lcobucci\JWT\Configuration;
use Lcobucci\JWT\Keys;
use Lcobucci\JWT\Signer;
use Lcobucci\JWT\Signer\Key;
use Lcobucci\JWT\Signer\Rsa\Sha256;
use Lcobucci\JWT\Signer\Rsa\Sha512;
Expand Down Expand Up @@ -63,7 +62,7 @@ public function builderShouldRaiseExceptionWhenKeyIsInvalid()
->canOnlyBeUsedBy('http://client.abc.com')
->issuedBy('http://api.abc.com')
->with('user', ['name' => 'testing', 'email' => '[email protected]'])
->sign($this->config->getSigner(), new Key('testing'));
->getToken($this->config->getSigner(), new Key('testing'));
}

/**
Expand All @@ -88,7 +87,7 @@ public function builderShouldRaiseExceptionWhenKeyIsNotRsaCompatible()
->canOnlyBeUsedBy('http://client.abc.com')
->issuedBy('http://api.abc.com')
->with('user', ['name' => 'testing', 'email' => '[email protected]'])
->sign($this->config->getSigner(), static::$ecdsaKeys['private']);
->getToken($this->config->getSigner(), static::$ecdsaKeys['private']);
}

/**
Expand All @@ -113,8 +112,7 @@ public function builderCanGenerateAToken()
->issuedBy('http://api.abc.com')
->with('user', $user)
->withHeader('jki', '1234')
->sign($this->config->getSigner(), static::$rsaKeys['private'])
->getToken();
->getToken($this->config->getSigner(), static::$rsaKeys['private']);

self::assertAttributeInstanceOf(Signature::class, 'signature', $token);
self::assertEquals('1234', $token->headers()->get('jki'));
Expand Down
2 changes: 1 addition & 1 deletion test/functional/UnsignedTokenTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public function builderCanGenerateAToken()
->issuedBy('http://api.abc.com')
->expiresAt(self::CURRENT_TIME + 3000)
->with('user', $user)
->getToken();
->getUnsecuredToken();

self::assertAttributeEquals(null, 'signature', $token);
self::assertEquals(['http://client.abc.com'], $token->claims()->get('aud'));
Expand Down
Loading

0 comments on commit 3eed588

Please sign in to comment.