JWT tokens, what they are for and how to work with them in PHP?

What is JWT
JWT-tokens (JSON Web Tokens) are a way of transferring data between a client and server in JSON format. They allow users to be authenticated, grant access to resources, and ensure the security of information exchange.
JWT tokens consist of three parts: a header, payload, and signature. The header contains information about the type of token and signature algorithm. The payload contains data stored in the token, such as a user ID or role. The signature guarantees the integrity and authenticity of the token.
Ways to use JWT tokens
JWT tokens can be used for various purposes in a web application:
Authentication: The client sends their credentials to the server, which verifies them and issues a token. The client saves the token in local storage or cookies and sends it with each request to the server. The server checks the token and determines who the client is.
Authorization: The token can contain information about the user's role or permissions. The server can check this information and allow or deny access to certain resources or actions.
Data exchange: The token can contain any data that needs to be passed between parties. For example, the token can contain payment or order data. The token can also be encrypted for additional security.
One such example is generating password reset strings: JWT can be used to create temporary links for resetting or changing a user's password. To do this, simply place a unique user identifier and token expiration in the token's payload. Then send the token to the user via email or another method. When the user clicks on the link with the token, the server can verify its authenticity and validity, and then allow the user to change their password.
Pros and cons
They are self-sufficient: They do not require storage on a server or database, as all data is already included in the token.
They are lightweight: They have a compact size and can be easily transferred through URLs, HTTP headers or QR codes.
Furthermore, they are versatile: They can be used for any type of application or platform, as they are based on the JSON standard.
However, JWT tokens also have disadvantages. They:
Cannot be revoked or updated.
Can be stolen or intercepted during insecure transmission or storage.
Can be susceptible to dictionary attacks or key guessing when using a weak key or algorithm.
💡
If you want the JWT token to no longer be authorized, it must be blacklisted (e.g. in the database).
Authentication implementation (access/refresh tokens)
JWT-tokens can be used to implement a mechanism for refreshing access tokens without the need to store them on the server. To do this, two types of tokens are issued: a short-lived access token and a long-lived refresh token. The access token contains minimal information about the user and their access rights to system resources. The refresh token contains only a unique user identifier and the token's expiration date. When the access token expires, the client sends the refresh token to the server to obtain a new access token.
😆
When I first started using these tokens, I was terribly worried about security. I was like "what, trust a user with a token that has an is_admin field". Let me tell you right away: you never have to worry about whether the user modified your token or not. If the token has been modified, it will not pass validation. I have checked it :D
How to work with them in PHP
To generate a JWT, you need to select an encryption algorithm (I recommend RSA256 because it is an asymmetric algorithm.), define the header and payload of the token in JSON format, and then sign this data using a secret key or key pair depending on the algorithm.
To work with JWT tokens in PHP, you will need the firebase/php-jwt
library, which can be installed using
composer require firebase/php-jwt
To create a token, you need to call the encode
method of the firebase/php-jwt
library, passing it the header, payload, and private key.
To decode a token, you need to call the decode
method of the firebase/php-jwt
library, passing it the token, public key, and a list of valid algorithms.
If the token is valid and not expired, the decode
method will return an object with data from the payload. However, if the token is invalid or expired, the decode method will throw an exception.
<?p
use Firebase\JWT\JWT;
$header = [
'alg' => 'RS256',
'typ' => 'JWT'
];
$payload = [
'iss' => 'https://example.com',
'sub' => 'user@example.com',
'exp' => time() + 3600,
'iat' => time(),
'nbf' => time(),
'data' => [
'user_id' => $userId,
'is_admin' => true
]
];
$private_key = <<<EOD
-----BEGIN RSA PRIVATE KEY-----
// some private key
-----END RSA PRIVATE KEY-----
EOD;
$public_key = <<<EOD
-----BEGIN PUBLIC KEY-----
// some public key
-----END PUBLIC KEY-----
EOD;
$token = JWT::encode($payload, $private_key, $header['alg']);
// Save the received $token on the client and pass it in the header "Authorization"
// Let's pretend you passed this $token from the client in the "Authorization" header
$token = $_SERVER['HTTP_AUTHORIZATION'];
$decoded = JWT::decode($token, $public_key, [$header['alg']]);
A great explanation of how JWT tokens work and their application for authentication: