Creating and Managing JWT Tokens in PHP
JSON Web Tokens (JWT) have become a popular method for securely transmitting information between parties in web development. In this guide, we’ll explore the creation, validation, and decoding of JWT tokens in PHP without relying on external libraries. We’ll leverage hash_hmac
for signature generation and base64_encode/decode
for encoding and decoding.
Setting Up Your Environment
Before we dive into the code, make sure you have PHP installed on your server. Additionally, you may want to use Composer to manage dependencies. In this example, we’ll create a standalone class to handle JWT operations.
composer init
composer require guzzlehttp/guzzle
The JWT Manager Class
Now, let’s create a class named JwtManager
that encapsulates the JWT operations:
<?php
class JwtManager
{
private $secretKey;
public function __construct($secretKey)
{
$this->secretKey = $secretKey;
}
public function createToken($payload)
{
// Implementation for creating JWT
}
public function validateToken($token)
{
// Implementation for validating JWT
}
public function decodeToken($token)
{
// Implementation for decoding JWT
}
// Helper functions for base64 URL encoding/decoding
}
Creating a JWT
Let’s implement the createToken
method for generating JWTs:
public function createToken($payload)
{
$base64UrlHeader = $this->base64UrlEncode(json_encode(["alg" => "HS256", "typ" => "JWT"]));
$base64UrlPayload = $this->base64UrlEncode(json_encode($payload));
$base64UrlSignature = hash_hmac('sha256', $base64UrlHeader . '.' . $base64UrlPayload, $this->secretKey, true);
$base64UrlSignature = $this->base64UrlEncode($base64UrlSignature);
return $base64UrlHeader . '.' . $base64UrlPayload . '.' . $base64UrlSignature;
}
private function base64UrlEncode($data)
{
$base64 = base64_encode($data);
$base64Url = strtr($base64, '+/', '-_');
return rtrim($base64Url, '=');
}
private function base64UrlDecode($data)
{
$base64 = strtr($data, '-_', '+/');
$base64Padded = str_pad($base64, strlen($base64) % 4, '=', STR_PAD_RIGHT);
return base64_decode($base64Padded);
}
Validating a JWT
Now, let’s implement the validateToken
method for validating JWTs:
public function validateToken($token)
{
// Implementation for validating JWT
list($base64UrlHeader, $base64UrlPayload, $base64UrlSignature) = explode('.', $token);
$signature = $this->base64UrlDecode($base64UrlSignature);
$expectedSignature = hash_hmac('sha256', $base64UrlHeader . '.' . $base64UrlPayload, $this->secretKey, true);
return hash_equals($signature, $expectedSignature);
}
Decoding a JWT
Finally, let’s implement the decodeToken
method for decoding JWTs:
public function decodeToken($token)
{
// Implementation for decoding JWT
list(, $base64UrlPayload, ) = explode('.', $token);
$payload = $this->base64UrlDecode($base64UrlPayload);
return json_decode($payload, true);
}
Examples: Putting It All Together
Let’s see how to use our JwtManager
class in practice:
<?php
// Include the JwtManager class
require 'vendor/autoload.php';
use JwtManager;
// Your secret key (keep this secure)
$secretKey = 'your_secret_key';
// Create an instance of JwtManager
$jwtManager = new JwtManager($secretKey);
// Create a JWT
$payload = [
"user_id" => 123,
"username" => "john_doe",
"exp" => time() + 3600, // Token expiration time (1 hour)
];
$jwt = $jwtManager->createToken($payload);
echo "JWT Token: " . $jwt . PHP_EOL;
// Validate and decode the JWT
if ($jwtManager->validateToken($jwt)) {
echo "JWT is valid." . PHP_EOL;
$decodedPayload = $jwtManager->decodeToken($jwt);
echo "Decoded Payload: " . json_encode($decodedPayload, JSON_PRETTY_PRINT);
} else {
echo "JWT is invalid.";
}
In this example, we create a JWT with a payload containing a user ID, username, and expiration time. We then validate and decode the JWT using our JwtManager
class.
Conclusion
Creating, validating, and decoding JWT tokens in PHP without external libraries can be a powerful and educational experience. By understanding the inner workings of JWTs, you gain greater control and flexibility in your authentication and authorization processes. Remember to use secure practices, such as keeping your secret key confidential and using HTTPS to protect the token during transmission.
Feel free to adapt and extend the JwtManager
class based on your specific requirements. As your PHP JWT implementation grows, consider exploring established libraries for production scenarios to benefit from additional features and security measures.
Happy coding!