Baguma
Baguma

Reputation: 373

How to generate JWT in PHP

How to generate JWT token in php using with the following parameters Subject, Issuer, Expiry time and payload in the < PAYLOAD > tag.

Sample request from Third Party is shown below

<COMMAND><TYPE>REQUEST</TYPE><INTERFACE>TESTACCOUNT</INTERFACE> <REQUESTID>123</REQUESTID></COMMAND

Upvotes: 7

Views: 13334

Answers (4)

solutionhacker
solutionhacker

Reputation: 288

Alot of the answers on here are great - JWT tokens are indeed a standard for authentication, especially for OAuth. If you are using either JavaScript or PHP for your application, here is an open-source library I wrote named "QuickJWT" that may solve your basic JWT needs. Using the QuickJWT library, you can make a JWT token easily like this:

$token = QuickJWT::sign($payload, $secret);

I've previously had problems finding suitable libraries myself to deal with JWT and so I decided to write one myself. That makes encoding, decoding, and validating JWT tokens easier. Usually, there's a lot of code involved, so I made QuickJWT simpler to work with.

Hope this gives you an idea of how to work with JWT tokens and decode their payloads for details. Take a look at QuickJWT:

https://github.com/dominicklee/Quick-JWT

Upvotes: 0

Neoistone
Neoistone

Reputation: 1

This JWT class provides the core functionality to encode and decode JSON Web Tokens (JWT) using a symmetric key (stored in APP_KEY).

<?php

namespace APP\Helpers;

class JWT
{
    private $signing_key;

    public function __construct()
    {
        // Clean up the key by removing "base64:" prefix and "=" padding
        $this->signing_key = str_replace(['base64:', '='], '', getenv('APP_KEY'));
    }

    public function encode(array $payload) : string
    {
        $header = [
            "alg" => "HS512",
            "typ" => "JWT"
        ];

        $encodedHeader = rtrim(strtr(base64_encode(json_encode($header)), '+/', '-_'), '=');
        $encodedPayload = rtrim(strtr(base64_encode(json_encode($payload)), '+/', '-_'), '=');

        $signature = hash_hmac('sha512', "$encodedHeader.$encodedPayload", $this->signing_key, true);
        $encodedSignature = rtrim(strtr(base64_encode($signature), '+/', '-_'), '=');

        return "{$encodedHeader}.{$encodedPayload}.{$encodedSignature}";
    }

    public function decode(string $token) : ?array
    {
        $tokenParts = explode('.', $token);

        if (count($tokenParts) !== 3) {
            return null; // Invalid JWT format
        }

        list($encodedHeader, $encodedPayload, $providedSignature) = $tokenParts;

        $header = json_decode(base64_decode(strtr($encodedHeader, '-_', '+/')), true);
        $payload = json_decode(base64_decode(strtr($encodedPayload, '-_', '+/')), true);
        $signature = base64_decode(strtr($providedSignature, '-_', '+/'));

        // Validate JSON decoding
        if ($header === null || $payload === null) {
            return null;
        }

        // Re-create signature
        $validSignature = hash_hmac('sha512', "$encodedHeader.$encodedPayload", $this->signing_key, true);

        if (!hash_equals($signature, $validSignature)) {
            return null; // Invalid signature
        }

        return [
            'header' => $header,
            'body' => $payload
        ];
    }
}

Example Usage

Encoding a Token

$jwtHelper = new \APP\Helpers\JWT();
$token = $jwtHelper->encode(['user_id' => 123, 'role' => 'admin']);
echo "JWT Token: " . $token;

Decoding a Token

$decoded = $jwtHelper->decode($token);
if ($decoded) {
    print_r($decoded); // Prints header and payload
} else {
    echo "Invalid token.";
}

Upvotes: 0

Baguma
Baguma

Reputation: 373

With the help of an article from DZone Security, I managed to generate a JWT token by doing the following

  1. Define the base64UrlEncode function which replaces + with -, / with _ and = with ''.
function base64UrlEncode($text)
{
    return str_replace(
        ['+', '/', '='],
        ['-', '_', ''],
        base64_encode($text)
    );
}

  1. Encode the headers using base64UrlEncode
$headers = [ "alg" => "HS512"];

$headers_encoded = $this->base64UrlEncode(json_encode($headers));
  1. Encode the Payload using Base64 URL encode as well
$issuedAt = time();

    $payload =  [
        "id" =>$this->gen_uuid(), //   .setId(UUID.randomUUID().toString())
        "sub"=> "TestService", //Subject
        "exp"=> $issuedAt+30,
        "iss"=> "Baguma Inc",  //issuer
        "iat"=> $issuedAt,  //issued at
        "PAYLOAD"=> "<COMMAND><TYPE>REQUEST</TYPE><INTERFACE>TESTACCOUNT</INTERFACE> <REQUESTID>123</REQUESTID></COMMAND"];

      $payload_encoded = $this->base64UrlEncode(json_encode($payload));
  1. Using the Key/secret build the signature
$key = "fcvxcnfrhrtghkfghgwerikdf";  
$signature = hash_hmac('sha512',"$headers_encoded.$payload_encoded",$key,true);

5 Encode the signature

$signature_encoded = $this->base64UrlEncode($signature);
  1. Build and return the token
$token = "$headers_encoded.$payload_encoded.$signature_encoded";

Upvotes: 7

cloudsurfin
cloudsurfin

Reputation: 2587

Your answer got me started. Here's the working code I went with (albeit generalized from your specific case). Thanks for getting me started!

function gen_jwt():String{
    $signing_key = "changeme";
    $header = [ 
        "alg" => "HS512", 
        "typ" => "JWT" 
    ];
    $header = base64_url_encode(json_encode($header));
    $payload =  [
        "exp" => 0,
    ];
    $payload = base64_url_encode(json_encode($payload));
    $signature = base64_url_encode(hash_hmac('sha512', "$header.$payload", $signing_key, true));
    $jwt = "$header.$payload.$signature";
    return $jwt;    
}

/**
 * per https://stackoverflow.com/questions/2040240/php-function-to-generate-v4-uuid/15875555#15875555
 */
function base64_url_encode($text):String{
    return str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($text));
}

Upvotes: 15

Related Questions