Introduction
In this post, I am going to show you how to generate a secret by using symfony vaults and then how to use that secret to encode and decode a JWT Token using the firebase-jwt php component.
Generating the secret
To generate a secret we must first generate the encryption keys. This can be done using the following command:
bin/console secrets:generate-keys
This will generate a key pair in the following files:
- config/secrets/{env}/{env}.encrypt.public.php
- config/secrets/{env}/{env}.decrypt.private.php
The {env} value will depend on the enviroment you are working. If you are developing in local it should be "dev".
Now we have generated the key-pair, we can create a secret. To do it, let's execute the following command:
bin/console secrets:set JWT_SECRET
The command will ask you for the secret value. Write it and press enter to save it.
Binding the JWT_SECRET to a variable
As we can get the JWT_SECRET value as we'd do with any other environment variable, let's bind a variable to it in our services.yaml file
services:
_defaults:
autowire: true
autoconfigure: true
bind:
# Other vars
$jwtSecret: '%env(JWT_SECRET)%'
Install the Firebase JWT PHP component
Let's use composer to install the component:
composer require firebase/php-jwt
If you do not have sodium installed, install it using composer too.
composer require paragonie/sodium_compat
Use the secret to encode and decode a jwt token
Let's create a service to encapsulate the logic which will encode and decode the tokens.
namespace App\Service\Token
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
class TokenEncoder
{
public function __construct(
private readonly string $jwtSecret,
){}
public function encode(string $exp, string $identifier): string
{
return JWT::encode([
'exp' => (new \DateTime())->add(\DateInterval::createFromDateString($exp))->getTimestamp(),
'nbf' => (new \DateTime())->getTimestamp(),
'id' => $identifier
], $this->jwtSecret, 'HS256');
}
public function decode(string $token): string
{
$credentials = (array)JWT::decode($token, new Key($this->jwtSecret, 'HS256'));
}
}
Let's analyze the service step by step:
- The constructor injects the recently binded variable in the services.yaml file ("$jwtSecret") which holds the JWT_SECRET value.
- The encode method encodes the token. It receives:
- The array to encode with the token. It contains the following keys:
- exp: The token expiration time as a timestamp
- nbf: Indicates when the token starts to be valid. We set the current timestamp, that is, when the token is created it starts to be valid until the expiration date.
- id: An identifier (Could be a user or application identifier).
- The secret to encode the token with (we use our $jwtSecret binded var).
- The encryption algorithm. We choose the HS256.
- The array to encode with the token. It contains the following keys:
You can learn more about HS256 and RS256 here. We choose HS256 since it is a symmetric hashing and we only need one secret key.
Conclusion
In this post we have learned how we can securely store a secret within symfony secrets and how to use it to generate a JWT token. This could be useful on API's which use JWT tokens to autenticate their users or applications.
Top comments (0)