Skip to content

Commit

Permalink
use property accessor for token field node path
Browse files Browse the repository at this point in the history
  • Loading branch information
eljam committed Sep 11, 2019
1 parent c8ea177 commit 488f5da
Show file tree
Hide file tree
Showing 6 changed files with 188 additions and 10 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
CHANGELOG
=========

This changelog will be used for bugfix for this version

# 0.7

* add property accessor to change node path for token and expire fields
36 changes: 35 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ $authStrategy = new JsonAuthStrategy(

## Persistence

To avoid requesting a token everytime php runs, you can pass to `JwtManager` an implementation of `TokenPersistenceInterface`.
To avoid requesting a token everytime php runs, you can pass to `JwtManager` an implementation of `TokenPersistenceInterface`.
By default `NullTokenPersistence` will be used.

### Simpe cache adapter (PSR-16)
Expand Down Expand Up @@ -217,6 +217,40 @@ class MyCustomPersistence implements TokenPersistenceInterface

## Token key


### Property accessor

With the property accessor you can point to a node in your json.

Json Example:

```javascript
{
"status": "success",
"message": "Login successful",
"payload": {
"token": "1453720507"
},
"expires_in": 3600
}
```

Library configuration:

```php
$jwtManager = new JwtManager(
$authClient,
$authStrategy,
$persistenceStrategy,
[
'token_url' => '/api/token',
'token_key' => 'payload.token',
'expire_key' => 'expires_in'
]
);
```

## Default behavior
By default this library assumes your json response has a key `token`, something like this:

```javascript
Expand Down
119 changes: 118 additions & 1 deletion Tests/Manager/JwtManagerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,123 @@
*/
class JwtManagerTest extends \PHPUnit_Framework_TestCase
{

/**
* testGetTokenExpiredKeyException
*/
public function testGetTokenExpiredKeyException()
{
$mockHandler = new MockHandler([
function (RequestInterface $request) {

$this->assertTrue($request->hasHeader('timeout'));
$this->assertEquals(
3,
$request->getHeaderLine('timeout')
);

$jsonPayload = <<<EOF
{
"status": "success",
"message": "Login successful",
"payload": {
"token": "1453720507"
},
"expires_in": 3600
}
EOF;

return new Response(
200,
['Content-Type' => 'application/json'],
$jsonPayload
);
},
]);

$handler = HandlerStack::create($mockHandler);

$authClient = new Client([
'handler' => $handler,
]);

$authStrategy = new QueryAuthStrategy(['username' => 'admin', 'password' => 'admin']);

$jwtManager = new JwtManager(
$authClient,
$authStrategy,
null,
[
'token_url' => '/api/token',
'timeout' => 3,
'token_key' => 'token',
'expire_key' => 'expires_in'
]
);

$this->setExpectedException('Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException');

$token = $jwtManager->getJwtToken();
}

/**
* testGetTokenWithSublevelResponse
*/
public function testGetTokenWithSublevelResponse()
{
$mockHandler = new MockHandler([
function (RequestInterface $request) {

$this->assertTrue($request->hasHeader('timeout'));
$this->assertEquals(
3,
$request->getHeaderLine('timeout')
);

$jsonPayload = <<<EOF
{
"status": "success",
"message": "Login successful",
"payload": {
"token": "1453720507"
},
"expires_in": 3600
}
EOF;

return new Response(
200,
['Content-Type' => 'application/json'],
$jsonPayload
);
},
]);

$handler = HandlerStack::create($mockHandler);

$authClient = new Client([
'handler' => $handler,
]);

$authStrategy = new QueryAuthStrategy(['username' => 'admin', 'password' => 'admin']);

$jwtManager = new JwtManager(
$authClient,
$authStrategy,
null,
[
'token_url' => '/api/token',
'timeout' => 3,
'token_key' => 'payload.token',
'expire_key' => 'expires_in'
]
);
$token = $jwtManager->getJwtToken();

$this->assertInstanceOf(JwtToken::class, $token);
$this->assertEquals('1453720507', $token->getToken());
}

/**
* testGetToken.
*/
Expand All @@ -33,7 +150,7 @@ function (RequestInterface $request) {
return new Response(
200,
['Content-Type' => 'application/json'],
json_encode(['token' => '1453720507'])
json_encode(['token' => '1453720507', 'expires_in' => 3600])
);
},
]);
Expand Down
5 changes: 3 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,15 @@
"php" : ">=5.6.0",
"guzzlehttp/guzzle": "~6.0",
"psr/simple-cache": "^1.0",
"symfony/options-resolver": ">=2.8"
"symfony/options-resolver": ">=2.8",
"symfony/property-access":">=2.8"
},
"config": {
"bin-dir" : "bin/"
},
"extra": {
"branch-alias": {
"dev-master": "0.4-dev"
"dev-master": "0.7-dev"
}
}
}
2 changes: 1 addition & 1 deletion src/JwtToken.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class JwtToken
private $token;

/**
* @var \DateTime
* @var \DateTime|null
*/
private $expiration;

Expand Down
28 changes: 23 additions & 5 deletions src/Manager/JwtManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
use GuzzleHttp\ClientInterface;
use GuzzleHttp\request;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\PropertyAccess\PropertyAccess;
use Symfony\Component\PropertyAccess\PropertyAccessor;
use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException;

/**
* @author Guillaume Cavana <[email protected]>
Expand Down Expand Up @@ -48,6 +51,12 @@ class JwtManager
*/
protected $tokenPersistence;

/**
* $propertyAccessor.
*
* @var PropertyAccessor
*/
protected $propertyAccessor;
/**
* Constructor.
*
Expand Down Expand Up @@ -81,6 +90,8 @@ public function __construct(
$resolver->setRequired(['token_url', 'timeout']);

$this->options = $resolver->resolve($options);

$this->propertyAccessor = PropertyAccess::createPropertyAccessor();
}

/**
Expand All @@ -95,7 +106,7 @@ public function getJwtToken()
$this->token = $this->tokenPersistence->restoreToken();
}

if ($this->token && $this->token->isValid()) {
if ($this->token !== null && $this->token->isValid()) {
return $this->token;
}

Expand All @@ -109,13 +120,20 @@ public function getJwtToken()
);

$response = $this->client->request('POST', $url, $requestOptions);
$body = json_decode($response->getBody(), true);
$body = json_decode($response->getBody());

//Will be throw because it's mandatory
$tokenValue = $this->propertyAccessor->getValue($body, $this->options['token_key']);

$expiresIn = isset($body[$this->options['expire_key']]) ? $body[$this->options['expire_key']] : null;
try {
$expiresIn = $this->propertyAccessor->getValue($body, $this->options['expire_key']);
} catch (NoSuchPropertyException $e) {
$expiresIn = null;
}

if ($expiresIn) {
$expiration = new \DateTime('now + ' . $expiresIn . ' seconds');
} elseif (count($jwtParts = explode('.', $body[$this->options['token_key']])) === 3
} elseif (count($jwtParts = explode('.', $tokenValue)) === 3
&& is_array($payload = json_decode(base64_decode($jwtParts[1]), true))
// https://tools.ietf.org/html/rfc7519.html#section-4.1.4
&& array_key_exists('exp', $payload)
Expand All @@ -126,7 +144,7 @@ public function getJwtToken()
$expiration = null;
}

$this->token = new JwtToken($body[$this->options['token_key']], $expiration);
$this->token = new JwtToken($tokenValue, $expiration);
$this->tokenPersistence->saveToken($this->token);

return $this->token;
Expand Down

0 comments on commit 488f5da

Please sign in to comment.