I've inherited a Symfony project that uses this controller to authenticate users:
class TokenController extends FOSRestController
{
public function postTokensAction(Request $request)
{
$username = $request->request->get('username');
$password = $request->request->get('password');
$user = $this->get('fos_user.user_manager')
->findUserByUsername($username);
if (!$user) {
throw $this->createNotFoundException();
}
$passwordEncoder = $this->get('security.password_encoder');
if(!$passwordEncoder->isPasswordValid($user, $password)) {
throw $this->createAccessDeniedException();
}
$groups = ['foo', 'bar'];
$context = SerializationContext::create()
->setGroups($groups);
$token = $this->get('lexik_jwt_authentication.encoder')
->encode(['username' => $user->getUsername()]);
$user = $this->get('jms_serializer')
->toArray($user, $context);
return new JsonResponse([
'token' => $token,
'user' => $user
]);
}
}
And the customer requests an update: token should expire 10 seconds after the login. So, following the documentation, I added this listener.
<?php
namespace AppBundle\EventListener;
use Lexik\Bundle\JWTAuthenticationBundle\Event\JWTCreatedEvent;
class JWTCreatedListener
{
public function onJWTCreated(JWTCreatedEvent $event)
{
$expiration = new \DateTime('now');
$expiration->add(new \DateInterval('PT10S'));
$payload = $event->getData();
$payload['exp'] = $expiration->getTimestamp();
$event->setData($payload);
}
}
And, of course, I've marked the listener to observe the event
acme_api.event.jwt_created_listener:
class: AppBundle\EventListener\JWTCreatedListener
tags:
- { name: kernel.event_listener, event: lexik_jwt_authentication.on_jwt_created, method: onJWTCreated }
If I get a token with Postman and use it to make following requests I can make those request for days and days. The token never expire. My JWTCreatedListener does not seem to work.
What's wrong?
They never expire because you are using a low level api which is the JWT encoder. As you can see (since you call it),
encode()
takes the payload. For getting token expiration, the payload must contain theexp
claim with the expiration timestamp as value.This is handled by the
lexik_jwt_authentication.jwt_manager
service which uses the value of thelexik_jwt_authentication.encoder.token_ttl
config option to determine the expiration date. Set it and uses$this->get('lexik_jwt_authentication.jwt_manager')->create($user)
for creating the token, then$this->get('lexik_jwt_authentication.jwt_manager')->decode($token)
at time to decode/verify it.Note that for using this bundle properly (allowing to hook into all the events it provides), you should consider using proper security configuration (as shown in the README) instead of doing this by hand in your controller.