Skip to content

Commit

Permalink
feature #786 Allow token creation from an existing payload (RicolaAC)
Browse files Browse the repository at this point in the history
This PR was squashed before being merged into the 2.x-dev branch.

Discussion
----------

Allow token creation from an existing payload

Add virtual method in JWTTokenManagerInterface to allow token creation from an existing payload

Commits
-------

8def9e6 Allow token creation from an existing payload
  • Loading branch information
chalasr committed Oct 27, 2020
2 parents 468ec17 + 8def9e6 commit e434f3b
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 5 deletions.
18 changes: 15 additions & 3 deletions Resources/doc/2-data-customization.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@ Table of contents
* [Customizing the response on token not found](#eventsjwt_not_found---customizing-the-response-on-token-not-found)
* [Customizing the response on expired token](#eventsjwt_expired---customizing-the-response-message-on-expired-token)

Events::JWT_CREATED - Adding custom data or headers to the JWT
Adding custom data or headers to the JWT
--------------------------------------------------------------

#### Using Events::JWT_CREATED

By default the JWT payload will contain the username and the token TTL,
but you can add your own data.

Expand All @@ -34,7 +36,7 @@ services:
- { name: kernel.event_listener, event: lexik_jwt_authentication.on_jwt_created, method: onJWTCreated }
```
#### Example: Add client ip to the encoded payload
##### Example: Add client ip to the encoded payload
``` php
// src/App/EventListener/JWTCreatedListener.php
Expand Down Expand Up @@ -76,7 +78,7 @@ public function onJWTCreated(JWTCreatedEvent $event)
}
```

#### Example: Override token expiration date calculation to be more flexible
##### Example: Override token expiration date calculation to be more flexible

``` php
// src/App/EventListener/JWTCreatedListener.php
Expand All @@ -100,6 +102,16 @@ public function onJWTCreated(JWTCreatedEvent $event)
}
```

#### Using a custom payload at JWT creation

If you [create JWT tokens programmatically](./7-manual-token-creation.md), you can add custom data to the JWT using the method `createFromPayload(UserInterface $user, array $payload)`

```php
$payload = ['foo' => 'bar'];

$jwt = $this->container->get('lexik_jwt_authentication.jwt_manager')->createFromPayload($user);
```

Events::JWT_DECODED - Validating data in the JWT payload
--------------------------------------------------------

Expand Down
31 changes: 29 additions & 2 deletions Services/JWTManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,19 +56,46 @@ public function __construct(JWTEncoderInterface $encoder, EventDispatcherInterfa
}

/**
* {@inheritdoc}
* @param UserInterface $user
* @param array $payload
*
* @return string The JWT token
*/
public function create(UserInterface $user)
{
$payload = ['roles' => $user->getRoles()];
$this->addUserIdentityToPayload($user, $payload);

return $this->generateJwtStringAndDispatchEvents($user, $payload);
}

/**
* @param UserInterface $user
* @param array $payload
*
* @return string The JWT token
*/
public function createFromPayload(UserInterface $user, array $payload)
{
$payload = array_merge(['roles' => $user->getRoles()], $payload);
$this->addUserIdentityToPayload($user, $payload);

return $this->generateJwtStringAndDispatchEvents($user, $payload);
}

/**
* @param UserInterface $user
* @param array $payload
*
* @return string The JWT token
*/
private function generateJwtStringAndDispatchEvents(UserInterface $user, array $payload)
{
$jwtCreatedEvent = new JWTCreatedEvent($payload, $user);
if ($this->dispatcher instanceof ContractsEventDispatcherInterface) {
$this->dispatcher->dispatch($jwtCreatedEvent, Events::JWT_CREATED);
} else {
$this->dispatcher->dispatch(Events::JWT_CREATED, $jwtCreatedEvent);

}

if ($this->jwtEncoder instanceof HeaderAwareJWTEncoderInterface) {
Expand Down
3 changes: 3 additions & 0 deletions Services/JWTTokenManagerInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
* JWT tokens.
*
* @author Robin Chalas <robin.chalas@gmail.com>
* @author Eric Lannez <eric.lannez@gmail.com>
*
* @method createFromPayload(UserInterface $user, array $payload = []);
*/
interface JWTTokenManagerInterface
{
Expand Down
51 changes: 51 additions & 0 deletions Tests/Services/JWTManagerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,57 @@ public function testCreate()
$this->assertEquals('secrettoken', $manager->create(new User('user', 'password')));
}

/**
* test create.
*/
public function testCreateFromPayload()
{
$dispatcher = $this->getEventDispatcherMock();

if ($dispatcher instanceof ContractsEventDispatcherInterface) {
$dispatcher
->expects($this->at(0))
->method('dispatch')
->with(
$this->isInstanceOf('Lexik\Bundle\JWTAuthenticationBundle\Event\JWTCreatedEvent'),
$this->equalTo(Events::JWT_CREATED)
);

$dispatcher
->expects($this->at(1))
->method('dispatch')
->with(
$this->isInstanceOf('Lexik\Bundle\JWTAuthenticationBundle\Event\JWTEncodedEvent'),
$this->equalTo(Events::JWT_ENCODED)
);
} else {
$dispatcher
->expects($this->at(0))
->method('dispatch')
->with(
$this->equalTo(Events::JWT_CREATED),
$this->isInstanceOf('Lexik\Bundle\JWTAuthenticationBundle\Event\JWTCreatedEvent')
);
$dispatcher
->expects($this->at(1))
->method('dispatch')
->with(
$this->equalTo(Events::JWT_ENCODED),
$this->isInstanceOf('Lexik\Bundle\JWTAuthenticationBundle\Event\JWTEncodedEvent')
);
}

$encoder = $this->getJWTEncoderMock();
$encoder
->expects($this->once())
->method('encode')
->willReturn('secrettoken');

$manager = new JWTManager($encoder, $dispatcher, 'username');
$payload = ['foo' => 'bar'];
$this->assertEquals('secrettoken', $manager->createFromPayload(new User('user', 'password'), $payload));
}

/**
* test decode.
*/
Expand Down

0 comments on commit e434f3b

Please sign in to comment.