I try to secure some files via Symfony. Let's say I access them via the following url:
https://test.com/file/?token=AAAABBBBCCCC
I already implemented authorization via LexikJWTAuthenticationBundle
. I log in; get an access token - this is working just fine. So I used my login access token to put in the url.
But login tokens have a far too long lifespan. So I thought about creating a short lifetime token (< 2 seconds), to just access the file once. As soon as I refresh the page, access to the file should be gone.
On the symfony page I found out how to create a token: $JWTManager->create($user)
(https://symfony.com/bundles/LexikJWTAuthenticationBundle/current/7-manual-token-creation.html)
But I cannot configure lifespan of this token. This is usually configured in lexik_jwt_authentication.yaml
, but I don't want change lifespan of the login token :/
I'm using Symfony 5.
Any ideas?
I solved it now. First create a token and add any data to identify its use case. I use for example a scoped:
public function createToken(JWTTokenManagerInterface $jwt): JsonResponse
{
$token = $jwt->createFromPayload(
$this->getUser(),
['scope' => 'fileScope']
);
return new JsonResponse($token);
}
Then use an EventListener to set expiry date based on scope:
// EventListener/JWTCreatedListener.php
declare(strict_types=1);
namespace App\EventListener;
use App\Controller\Authentication\GetDocumentFileToken;
use Lexik\Bundle\JWTAuthenticationBundle\Event\JWTCreatedEvent;
/**
* Class JWTCreatedListener
*/
class JWTCreatedListener
{
/**
* @param JWTCreatedEvent $event
*
* @return void
*/
public function onJWTCreated(JWTCreatedEvent $event): void
{
$payload = $event->getData();
if (($payload['scope'] ?? '') === 'fileScope') {
$expiration = new \DateTime('+1 minute');
$payload['exp'] = $expiration->getTimestamp();
}
$event->setData($payload);
}
}
And then, in the controller where only specific scope tokens are allowed:
public function getDocumentFile(JWTTokenManagerInterface $jwt): JsonResponse
{
$token = /* Get token from request or something */;
$tokenData = $jwt->parse($token);
if (($tokenData['scope'] ?? '') !== 'fileScope') {
return new JsonResponse('Permission denied', 400);
}
// Token is valid and fileScope so output file
}