Build and Verify JWT Tokens in PHP Without External Libraries
This guide walks you through setting up a PHP environment, creating a lightweight Jwt class that generates, validates, and decodes JSON Web Tokens using only built‑in functions like hash_hmac and base64, and demonstrates a full usage example with sample output.
This guide demonstrates how to implement JSON Web Token (JWT) creation, validation, and decoding in pure PHP without external libraries, using hash_hmac for HMAC‑SHA256 signatures and URL‑safe Base64 encoding.
Environment Setup
Make sure PHP (>=7.4) is installed. Composer can be used for project scaffolding, although the JWT class is self‑contained.
composer init
composer require guzzlehttp/guzzleJwt Class Overview
The Jwt class stores a secret key and provides three public methods:
createToken(array $payload): string – builds the JWT header, encodes the payload, signs the data with HMAC‑SHA256, and returns the compact token.
validateToken(string $token): bool – splits the token, recomputes the expected signature, and compares it with hash_equals to avoid timing attacks.
decodeToken(string $token): array – extracts the payload part, decodes it from Base64, and returns the JSON payload as an associative array.
Two private helper methods handle URL‑safe Base64 transformations.
<?php
class Jwt {
private string $secretKey;
public function __construct(string $secretKey) {
$this->secretKey = $secretKey;
}
// Create a JWT token
public function createToken(array $payload): string {
$header = $this->base64UrlEncode(json_encode(["alg" => "HS256", "typ" => "JWT"]));
$body = $this->base64UrlEncode(json_encode($payload));
$sig = hash_hmac('sha256', $header . '.' . $body, $this->secretKey, true);
$signature = $this->base64UrlEncode($sig);
return $header . '.' . $body . '.' . $signature;
}
// Validate a JWT token
public function validateToken(string $token): bool {
list($header, $body, $signature) = explode('.', $token);
$expected = hash_hmac('sha256', $header . '.' . $body, $this->secretKey, true);
return hash_equals($this->base64UrlDecode($signature), $expected);
}
// Decode a JWT token
public function decodeToken(string $token): array {
list(, $body, ) = explode('.', $token);
$json = $this->base64UrlDecode($body);
return json_decode($json, true);
}
// URL‑safe Base64 encode
private function base64UrlEncode(string $data): string {
return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
}
// URL‑safe Base64 decode
private function base64UrlDecode(string $data): string {
$b64 = strtr($data, '-_', '+/');
$pad = strlen($b64) % 4;
if ($pad) {
$b64 .= str_repeat('=', 4 - $pad);
}
return base64_decode($b64);
}
}
?>Usage Example
The following script shows how to instantiate the class, create a token with an expiration claim, validate the token, and decode the payload.
<?php
require 'vendor/autoload.php';
$secretKey = 'Tinywan2024040000011';
$jwt = new Jwt($secretKey);
$payload = [
"user_id" => 2024,
"username" => "Tinywan",
"exp" => time() + 3600 // expires in 1 hour
];
$token = $jwt->createToken($payload);
echo "JWT Token: " . $token . PHP_EOL;
if ($jwt->validateToken($token)) {
echo "JWT is valid." . PHP_EOL;
$decoded = $jwt->decodeToken($token);
echo "Decoded Payload: " . json_encode($decoded, JSON_PRETTY_PRINT) . PHP_EOL;
var_dump($decoded);
} else {
echo "JWT is invalid." . PHP_EOL;
}
?>Running the script prints a token string, confirms its validity, and displays the payload both as formatted JSON and as a PHP array.
Source code repository: https://github.com/Tinywan/jwt
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Open Source Tech Hub
Sharing cutting-edge internet technologies and practical AI resources.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
