JSON Web Token (JWT) is a JSON-based open standard used to create access tokens that assert some number of claims. In a palpable example, the JWT represents a key between a server-client relation: the server generates a token that has the claim “logged in as admin” and give it to a client, which could use that token to prove that is logged in as admin. The tokens are designed to be compact, URL-safe and can also be authenticated or encrypted.
JSON Web Tokens commonly consist of three parts: a header, a payload and a signature. The header identifies which algorithm is used to generate the signature, and looks something like this:
header = '{"alg":"HS256","typ":"JWT"}'
HS256 indicates that this token is signed using HMAC-SHA256.
The payload contains the claims that we wish to make:
payload = '{"loggedInAs":"admin","iat":1422779638}'
The signature is calculated by base64url encoding the header and payload and then concatenating them with a period as a separator:
key = 'secretkey'
unsignedToken = encodeBase64(header) + '.' + encodeBase64(payload)
signature = HMAC-SHA256(key, unsignedToken)
As we said above, the final token represents the base64url encoded signature, and couple together the three parts using periods:
token = encodeBase64(header) + '.' + encodeBase64(payload) + '.' + encodeBase64(signature) # token is now: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJsb2dnZWRJbkFzIjoiYWRtaW4iLCJpYXQiOjE0MjI3Nzk2Mzh9.gzSraSYS8EXBxLN_oWnFSRgCzcmJmMjLiuyu5CSpyHI
The resulting token is three Base64 strings separated by dots that can be easily passed in HTML and HTTP environments. In authentication, when the user successfully logs in using their credentials, a JSON Web Token will be returned and must be saved locally (typically in local storage), instead of the traditional approach of creating a session in the server and returning a cookie. When sending data from an application to a backend server it is a good idea to use JSON web token (JWT) to make sure the data has not been altered. The token is compact, making it quick to send to the backend.
Creating a JWT with PHP
The next section describes step-by-step how to create a JSON Web Token in PHP. To create a JSON web token we make use of the two PHP methods described below:
• string json_encode (mixed $value [, int $options = 0 [, int $depth = 512 ]] ) — Returns the JSON representation of a value where the $value argument can be any type except a resource
• string base64_encode ( string $data ) — encodes the given data with base64.
1. Encoding a header JSON Object and then base64 encode it.
The first step in creating a JWT is to set the first part of the token, which is the header, then encode it and base64 it, using the above two PHP methods:
<?php
//setting the header: 'alg' => 'HS256' indicates that this token is signed using HMAC-SHA256
$header = [
'typ' => 'JWT',
'alg' => 'HS256'
];
// Returns the JSON representation of the header
$header = json_encode($header);
//encodes the $header with base64.
$header = base64_encode($header);
//list the resulted header
print_r($header);
?>
The output of the above listing is:
2. Base64 encode a payload JSON Object.
After creating the header, we need to create the payload. Our payload looks like this:
$payload = ["country" => "Romania", "name" => "Octavia-Anghel", "email" => [email protected]];
To encode the payload we use again the two methods described above: json_encode and base64_encode
, like this:
$payload = json_encode($header);
$payload = base64_encode($header);
3. Concatenate the header and payload strings with “.” Separator.
After encoding the payload, we need to concatenate the header with the payload like this:
$header.$payload.
Next listing outputs the header and the payload, as you can see from the figure below.
<?php
$header = [
'typ' => 'JWT',
'alg' => 'HS256'
];
$header = json_encode($header);
$header = base64_encode($header);
//setting the payload
$payload = [
"country" => "Romania",
"name" => "Octavia-Anghel",
"email" => "[email protected]"
];
// Returns the JSON representation of the payload
$payload = json_encode($header);
//encodes the $payload with base64.
$payload = base64_encode($header);
echo "$header.$payload";
?>
The output of the above listing is:
4. Compute the signature of the header and payload.
Next step in creating a JWT in PHP is to set the signature by generate it using HMAC method.
$signature = hash_hmac('sha256','$header.$payload', $key, true);
You will notice that the $key arguments is used at generating the signature. It represents your personal password and is used to validate the signature, as you will see next in this article. In this case the $key is 'Octavia-Andrea-Anghel'
.
<?php
//setting the personal key identification
$key = 'Octavia-Andrea-Anghel';
$header = [
'typ' => 'JWT',
'alg' => 'HS256'
];
$header = json_encode($header);
$header = base64_encode($header);
$payload = [
"country" => "Romania",
"name" => "Octavia-Anghel",
"email" => "[email protected]"
];
$payload = json_encode($header);
$payload = base64_encode($header);
// Generates a keyed hash value using the HMAC method
$signature = hash_hmac('sha256','$header.$payload', $key, true);
echo $signature;
?>
The output of the above listing is:
5. Base64 encode the signature.
Before performing the last step in creating the final token, we need to base64 encode also the signature, using this line of code:
$signature = base64_encode($signature);
6. Concatenate the signature to the header and payload string.
The final step in creating our token is to concatenate all the strings: the header, the payload and the signature using this line:
$token = "$header.$payload.$signature";
Next listing puts together all the above steps described above and outputs the resulted token:
<?php
$key = 'Octaviasecretkey';
$header = [
'typ' => 'JWT',
'alg' => 'HS256'
];
$header = json_encode($header);
$header = base64_encode($header);
$payload = [
"country" => "Romania",
"name" => "Octavia-Anghel",
"email" => "[email protected]"
];
$payload = json_encode($header);
$payload = base64_encode($header);
// Generates a keyed hash value using the HMAC method
$signature = hash_hmac('sha256','$header.$payload', $key, true);
//base64 encode the signature
$signature = base64_encode($signature);
//concatenating the header, the payload and the signature to obtain the JWT token
$token = "$header.$payload.$signature";
echo $token;
?>
The result of the listing above is:
eyJhbGciOiAiSFMyNTYiLCJ0eXAiOiAiSldUIn0=.eyJjb3VudHJ5IjogIlJvbWFuaWEiLCJuYW1lIjogIk9jdGF2aWEgQW5naGVsIiwiZW1haWwiOiAib2N0YXZpYWFuZ2hlbEBnbWFpbC5jb20ifQ==.gbB+B063g+kwsoc4L3B1Bu2wM+VEBElwPiLOb0fj2SE=
Now, if we want to check that everything went well, we can test the token in https://jwt.io/ by pasting it in the Encoded section. You will then see on the right side, at the Decode section, all of your data. But for your signature can validate it, you need to enter your secret key at the bottom of the page, at the Verify Signature section, as you can see from the next figure:
Next listing is the “compressed” version of the above listing, the output of this listing is identical with the first one:
<?php
// base64 encodes the header json
$encoded_header = base64_encode('{"alg": "HS256","typ": "JWT"}');
// base64 encodes the payload json
$encoded_payload = base64_encode('{"country": "Romania","name": "Octavia Anghel","email": "[email protected]"}');
// base64 strings are concatenated to one that looks like this
$header_payload = $encoded_header . '.' . $encoded_payload;
//Setting the secret key
$secret_key = 'Octaviasecretkey';
// Creating the signature, a hash with the s256 algorithm and the secret key. The signature is also base64 encoded.
$signature = base64_encode(hash_hmac('sha256', $header_payload, $secret_key, true));
// Creating the JWT token by concatenating the signature with the header and payload, that looks like this:
$jwt_token = $header_payload . '.' . $signature;
//listing the resulted JWT
echo $jwt_token;
?>
The output of this listing is:
eyJhbGciOiAiSFMyNTYiLCJ0eXAiOiAiSldUIn0=.eyJjb3VudHJ5IjogIlJvbWFuaWEiLCJuYW1lIjogIk9jdGF2aWEgQW5naGVsIiwiZW1haWwiOiAib2N0YXZpYWFuZ2hlbEBnbWFpbC5jb20ifQ==.gbB+B063g+kwsoc4L3B1Bu2wM+VEBElwPiLOb0fj2SE=Verifying signature
Verifying the Signature
In this section, after creating a token in PHP, we want to verify that a received signature is correct. The next listing gets the token, extracts the signature from it, creates a new signature using the header and payload extracted from the received token (using also the $secret_key) and then compare the two signature. If everything went right you should get a success message:
<?php
$recievedJwt = 'eyJhbGciOiAiSFMyNTYiLCJ0eXAiOiAiSldUIn0=.eyJjb3VudHJ5IjogIlJvbWFuaWEiLCJuYW1lIjogIk9jdGF2aWEgQW5naGVsIiwiZW1haWwiOiAib2N0YXZpYWFuZ2hlbEBnbWFpbC5jb20ifQ==.gbB+B063g+kwsoc4L3B1Bu2wM+VEBElwPiLOb0fj2SE=';
$secret_key = 'Octaviasecretkey';
// Split a string by '.'
$jwt_values = explode('.', $recievedJwt);
// extracting the signature from the original JWT
$recieved_signature = $jwt_values[2];
// concatenating the first two arguments of the $jwt_values array, representing the header and the payload
$recievedHeaderAndPayload = $jwt_values[0] . '.' . $jwt_values[1];
// creating the Base 64 encoded new signature generated by applying the HMAC method to the concatenated header and payload values
$resultedsignature = base64_encode(hash_hmac('sha256', $ recievedHeaderAndPayload, $secret_key, true));
// checking if the created signature is equal to the received signature
if($resultedsignature == $recieved_signature) {
// If everything worked fine, if the signature is ok and the payload was not modified you should get a success message
echo "Success";
}
?>
During this article, you’ve learned how to create a JSON web token in PHP, how to test it and how to verify a received token if is correct. In conclusion, a JSON web token is quite easy to create and to validate it yourself. The secret key should not get into the wrong hands, otherwise you can not trust the signatures anymore and would need to change them.