Skip to content

Commit

Permalink
Merge branch 'feature/allow-multiple-audiences-and-issuers'
Browse files Browse the repository at this point in the history
  • Loading branch information
lcobucci committed Aug 14, 2016
2 parents 86dd75b + d446df1 commit 3245ccd
Show file tree
Hide file tree
Showing 19 changed files with 361 additions and 55 deletions.
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,25 @@ echo $token->getClaim('uid'); // will print "1"
echo $token; // The string representation of the object is a JWT string (pretty easy, right?)
```

If we have multiple possible members in the audience of a given token, we can set multiple audience members like so:

```php
use Lcobucci\JWT\Configuration;

$config = new Configuration(); // This object helps to simplify the creation of the dependencies
// instead of using "?:" on constructors.

$token = $config->createBuilder()
->setIssuer('http://example.com')
->setAudience(['http://example.org', 'http://example.com', 'http://example.io']) // Sets all three as audience members of this token.
->setId('4f1g23a12aa', true)
->setIssuedAt(time())
->setNotBefore(time() + 60)
->setExpiration(time() + 3600)
->set('uid', 1)
->getToken();
```

### Parsing from strings

Use the parser to create a new token from a JWT string (using the previous token as example):
Expand All @@ -75,6 +94,7 @@ $token->getClaims(); // Retrieves the token claims

echo $token->getHeader('jti'); // will print "4f1g23a12aa"
echo $token->getClaim('iss'); // will print "http://example.com"
echo $token->getClaim('aud')[0]; // will print "http://example.org"
echo $token->getClaim('uid'); // will print "1"
```

Expand All @@ -101,6 +121,14 @@ $data->setCurrentTime(time() + 4000); // changing the validation time to future
var_dump($token->validate($data)); // false, because token is expired since current time is greater than exp
```

If we have multiple possible issuers of an equivalent token, then it is possible to set multiple issuers to the ```ValidationData``` object:

```php
$data = new ValidationData();
$data->setIssuer(['http://example.com', 'http://example.io']);
$data->setAudience('http://example.org');
```

#### Important

- You have to configure ```ValidationData``` informing all claims you want to validate the token.
Expand Down
14 changes: 11 additions & 3 deletions src/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,22 @@ public function __construct(
/**
* Configures the audience
*
* @param string $audience
* @param string|array $audience
* @param bool $replicateAsHeader
*
* @return Builder
*/
public function setAudience(string $audience, bool $replicateAsHeader = false): Builder
public function setAudience($audience, bool $replicateAsHeader = false): Builder
{
return $this->setRegisteredClaim('aud', $audience, $replicateAsHeader);
if (!is_array($audience)) {
$audience = [$audience];
}

return $this->setRegisteredClaim(
'aud',
array_values(array_map('strval', $audience)),
$replicateAsHeader
);
}

/**
Expand Down
34 changes: 34 additions & 0 deletions src/Claim/ContainedEqualsTo.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/

declare(strict_types=1);

namespace Lcobucci\JWT\Claim;

use Lcobucci\JWT\Claim;
use Lcobucci\JWT\ValidationData;

/**
* Validatable claim that checks if claim value is strictly equal to an item in the given validation data set.
*
* @author Matthew John Marshall <matthew.marshall96@yahoo.co.uk>
* @since 4.0.0
*/
class ContainedEqualsTo extends Basic implements Claim, Validatable
{
/**
* {@inheritdoc}
*/
public function validate(ValidationData $data) : bool
{
if ($data->has($this->getName())) {
return in_array($this->getValue(), $data->get($this->getName()));
}

return true;
}
}
34 changes: 34 additions & 0 deletions src/Claim/ContainsEqualsTo.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/

declare(strict_types=1);

namespace Lcobucci\JWT\Claim;

use Lcobucci\JWT\Claim;
use Lcobucci\JWT\ValidationData;

/**
* Validatable claim that checks if the claim value set contains a value strictly equal to the validation item value.
*
* @author Matthew John Marshall <matthew.marshall96@yahoo.co.uk>
* @since 4.0.0
*/
class ContainsEqualsTo extends Basic implements Claim, Validatable
{
/**
* {@inheritdoc}
*/
public function validate(ValidationData $data) : bool
{
if ($data->has($this->getName())) {
return in_array($data->get($this->getName()), $this->getValue());
}

return true;
}
}
30 changes: 28 additions & 2 deletions src/Claim/Factory.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ public function __construct(array $callbacks = [])
'iat' => [$this, 'createLesserOrEqualsTo'],
'nbf' => [$this, 'createLesserOrEqualsTo'],
'exp' => [$this, 'createGreaterOrEqualsTo'],
'iss' => [$this, 'createEqualsTo'],
'aud' => [$this, 'createEqualsTo'],
'iss' => [$this, 'createContainedEqualsTo'],
'aud' => [$this, 'createContainsEqualsTo'],
'sub' => [$this, 'createEqualsTo'],
'jti' => [$this, 'createEqualsTo']
],
Expand Down Expand Up @@ -103,6 +103,32 @@ private function createEqualsTo(string $name, $value): EqualsTo
return new EqualsTo($name, $value);
}

/**
* Creates a claim that can be compared (contained equals).
*
* @param string $name
* @param mixed $value
*
* @return ContainedEqualsTo
*/
protected function createContainedEqualsTo(string $name, $value): ContainedEqualsTo
{
return new ContainedEqualsTo($name, $value);
}

/**
* Creates a claim that can be compared (contains equals).
*
* @param string $name
* @param mixed $value
*
* @return ContainsEqualsTo
*/
protected function createContainsEqualsTo(string $name, $value): ContainsEqualsTo
{
return new ContainsEqualsTo($name, $value);
}

/**
* Creates a basic claim
*
Expand Down
10 changes: 7 additions & 3 deletions src/ValidationData.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,15 @@ public function setId(string $id)
/**
* Configures the issuer
*
* @param string $issuer
* @param string|array $issuer
*/
public function setIssuer(string $issuer)
public function setIssuer($issuer)
{
$this->items['iss'] = $issuer;
if (!is_array($issuer)) {
$issuer = [$issuer];
}

$this->items['iss'] = array_values(array_map('strval', $issuer));
}

/**
Expand Down
2 changes: 1 addition & 1 deletion test/functional/EcdsaTokenTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ public function builderCanGenerateAToken()

$this->assertAttributeInstanceOf(Signature::class, 'signature', $token);
$this->assertEquals('1234', $token->getHeader('jki'));
$this->assertEquals('http://client.abc.com', $token->getClaim('aud'));
$this->assertEquals(['http://client.abc.com'], $token->getClaim('aud'));
$this->assertEquals('http://api.abc.com', $token->getClaim('iss'));
$this->assertEquals($user, $token->getClaim('user'));

Expand Down
2 changes: 1 addition & 1 deletion test/functional/HmacTokenTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public function builderCanGenerateAToken()

$this->assertAttributeInstanceOf(Signature::class, 'signature', $token);
$this->assertEquals('1234', $token->getHeader('jki'));
$this->assertEquals('http://client.abc.com', $token->getClaim('aud'));
$this->assertEquals(['http://client.abc.com'], $token->getClaim('aud'));
$this->assertEquals('http://api.abc.com', $token->getClaim('iss'));
$this->assertEquals($user, $token->getClaim('user'));

Expand Down
2 changes: 1 addition & 1 deletion test/functional/RsaTokenTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ public function builderCanGenerateAToken()

$this->assertAttributeInstanceOf(Signature::class, 'signature', $token);
$this->assertEquals('1234', $token->getHeader('jki'));
$this->assertEquals('http://client.abc.com', $token->getClaim('aud'));
$this->assertEquals(['http://client.abc.com'], $token->getClaim('aud'));
$this->assertEquals('http://api.abc.com', $token->getClaim('iss'));
$this->assertEquals($user, $token->getClaim('user'));

Expand Down
2 changes: 1 addition & 1 deletion test/functional/UnsignedTokenTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public function builderCanGenerateAToken()
->getToken();

$this->assertAttributeEquals(null, 'signature', $token);
$this->assertEquals('http://client.abc.com', $token->getClaim('aud'));
$this->assertEquals(['http://client.abc.com'], $token->getClaim('aud'));
$this->assertEquals('http://api.abc.com', $token->getClaim('iss'));
$this->assertEquals(self::CURRENT_TIME + 3000, $token->getClaim('exp'));
$this->assertEquals($user, $token->getClaim('user'));
Expand Down
18 changes: 18 additions & 0 deletions test/unit/BuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,24 @@ public function setAudienceMustChangeTheAudClaim()
$this->assertAttributeEquals(['aud' => $this->defaultClaim], 'claims', $builder);
}

/**
* @test
*
* @uses Lcobucci\JWT\Builder::__construct
* @uses Lcobucci\JWT\Builder::set
*
* @covers Lcobucci\JWT\Builder::setAudience
* @covers Lcobucci\JWT\Builder::setRegisteredClaim
*/
public function setAudienceMustAcceptArrayOfValues()
{
$builder = $this->createBuilder();
$builder->setAudience(['test', 'test2']);

$this->assertAttributeEquals(['alg' => 'none', 'typ' => 'JWT'], 'headers', $builder);
$this->assertAttributeEquals(['aud' => $this->defaultClaim], 'claims', $builder);
}

/**
* @test
*
Expand Down
70 changes: 70 additions & 0 deletions test/unit/Claim/ContainedEqualsToTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/

declare(strict_types=1);

namespace Lcobucci\JWT\Claim;

use Lcobucci\JWT\ValidationData;

/**
* @author Matthew John Marshall <matthew.marshall96@yahoo.co.uk>
* @since 4.0.0
*/
class ContainedEqualsToTest extends \PHPUnit_Framework_TestCase
{
/**
* @test
*
* @uses Lcobucci\JWT\Claim\Basic
* @uses Lcobucci\JWT\ValidationData
*
* @covers Lcobucci\JWT\Claim\ContainedEqualsTo::validate
*/
public function validateShouldReturnTrueWhenValidationDoesntHaveTheClaim()
{
$claim = new ContainedEqualsTo('iss', 'test');

$this->assertTrue($claim->validate(new ValidationData()));
}

/**
* @test
*
* @uses Lcobucci\JWT\Claim\Basic
* @uses Lcobucci\JWT\ValidationData
*
* @covers Lcobucci\JWT\Claim\ContainedEqualsTo::validate
*/
public function validateShouldReturnTrueWhenClaimValueIsEqualToAtLeastOneItemInValidationData()
{
$claim = new ContainedEqualsTo('iss', 'test');

$data = new ValidationData();
$data->setIssuer(['test', 'test2']);

$this->assertTrue($claim->validate($data));
}

/**
* @test
*
* @uses Lcobucci\JWT\Claim\Basic
* @uses Lcobucci\JWT\ValidationData
*
* @covers Lcobucci\JWT\Claim\ContainedEqualsTo::validate
*/
public function validateShouldReturnFalseWhenClaimValueIsNotEqualToAtLeastOneItemInValidationData()
{
$claim = new ContainedEqualsTo('iss', 'test');

$data = new ValidationData();
$data->setIssuer(['test2', 'test3']);

$this->assertFalse($claim->validate($data));
}
}
Loading

0 comments on commit 3245ccd

Please sign in to comment.