Creating and Managing JWT Tokens in PHP

Seliesh Jacob
3 min readDec 8, 2023

--

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!

--

--