Skip to content

Instantly share code, notes, and snippets.

@nkpremices
Created January 14, 2022 18:20
Show Gist options
  • Save nkpremices/2d1495663c7f5bffa1bd0b873e69522b to your computer and use it in GitHub Desktop.
Save nkpremices/2d1495663c7f5bffa1bd0b873e69522b to your computer and use it in GitHub Desktop.
Generate you own jwt library with plain PHP. Prerequesites PHP 7.3.5 – 7.4.23
<?php
/*
To generate JWT you need mainly header, payload and secret.
Next you create a signature from the encoded header, the encoded payload, a secret,
the algorithm specified in the header.
The header is a JSON object with the following properties:
{
"alg": "HS256",
"typ": "JWT"
}
Then, this JSON is Base64Url encoded to form the first part of the JWT.
The second part of the token is the payload, which contains the claims.
Claims are statements about an entity (typically, the user) and additional data.
There are three types of claims: registered, public, and private claims.
For more information on each type you can read https://jwt.io/introduction/.
An example payload could be:
{
"id": "1234567890",
"name": "John Doe",
"admin": true
}
The payload is then Base64Url encoded to form the second part of the JSON Web Token.
The last part is the signature
For example if you want to use the HMAC SHA256 algorithm, the signature will be created in the following way:
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
*/
// Generate JWT
// To generate a jwt we will need a custom function called base64url_encode
// Here is the Base64-URL encoded function definition:
function base64url_encode($str) {
return rtrim(strtr(base64_encode($str), '+/', '-_'), '=');
}
// The output of the generated JWT is three Base64-URL strings separated by dots.
function generate_jwt($headers, $payload, $secret = 'skfmnskdjsnfkjnbkasjdknsjdnlasnksjdkj') {
$headers_encoded = base64url_encode(json_encode($headers));
$payload_encoded = base64url_encode(json_encode($payload));
$signature = hash_hmac('SHA256', "$headers_encoded.$payload_encoded", $secret, true);
$signature_encoded = base64url_encode($signature);
$jwt = "$headers_encoded.$payload_encoded.$signature_encoded";
return $jwt;
}
// Following is an example of how to generate JWT:
$headers = array('alg'=>'HS256','typ'=>'JWT');
$payload = array('id'=>'1234567890','name'=>'John Doe', 'admin'=>true, 'exp'=>(time() + 60));
$jwt = generate_jwt($headers, $payload);
echo($jwt);
echo("\n");
// echo $jwt;
/*
Now you got the JWT generated in the above step.
It’s time to verify whether you get the same header and payload from the JWT.
Hence you will need to validate your generated JWT.
*/
function is_jwt_valid($jwt, $secret = 'secret') {
// split the jwt
$tokenParts = explode('.', $jwt);
$header = base64_decode($tokenParts[0]);
$payload = base64_decode($tokenParts[1]);
$signature_provided = $tokenParts[2];
// check the expiration time - note this will cause an error if there is no 'exp' claim in the jwt
$expiration = json_decode($payload)->exp;
$is_token_expired = ($expiration - time()) < 0;
// build a signature based on the header and payload using the secret
$base64_url_header = base64url_encode($header);
$base64_url_payload = base64url_encode($payload);
$signature = hash_hmac('SHA256', $base64_url_header . "." . $base64_url_payload, $secret, true);
$base64_url_signature = base64url_encode($signature);
// verify it matches the signature provided in the jwt
$is_signature_valid = ($base64_url_signature === $signature_provided);
if ($is_token_expired || !$is_signature_valid) {
return array('isValid'=>'false','payload'=>$payload);
} else {
return array('isValid'=>'true','payload'=>$payload);
}
}
// if ($is_token_expired || !$is_signature_valid) {
// return array('isValid'=>'false','payload'=>$payload);
// } else {
// return array('isValid'=>'true','payload'=>$payload);
// }
//Following is an example of validating generated JWT:
$is_jwt_valid = is_jwt_valid($jwt);
echo("\n");
function printAnArray($stuff) {
foreach ($stuff as $key => $value) {
echo "$key: $value\n";
}
}
printAnArray($is_jwt_valid);
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment