Example of php Backend Implementation JWT Authentication Method

  • 2021-11-01 02:29:52
  • OfStack

What is JWT

JWT is that abbreviation of json web token. It encrypts user information into token, and the server does not save any user information. The server verifies the correctness of the token by using the saved key, and passes the verification as long as it is correct. token-based authentication can replace the traditional cookie+session authentication method.

It defines a concise, self-contained method for securely transferring information between two communicating parties in the form of JSON objects. JWT can be signed using the HMAC algorithm or the public key pair of RSA. It has two characteristics:

Simple (Compact): It can be sent through URL, POST parameters or HTTP header because of the small amount of data and high transmission speed

Self-contained (Self-contained): The payload contains all the information needed by users, avoiding multiple queries to the database

JWT consists of three parts: header.payload.signature

The following example takes JWT official website as an example

header section:


{
 "alg": "HS256",
 "typ": "JWT"
}

The corresponding base64UrlEncode code is: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

Description: This field is in json format. The alg field specifies the algorithm for generating signature, with a default value of HS256 and a default value of typ of JWT

payload section:


{
 "sub": "1234567890",
 "name": "John Doe",
 "iat": 1516239022
}

The corresponding base64UrlEncode code is: eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
This field is json format, indicating the user identity of the data, you can customize the field, very flexible. sub target users, name name, iat issue time. For example, customizable examples are as follows:


{
  "iss": "admin",     // The JWT Issuer of 
  "iat": 1535967430,    // Issue time 
  "exp": 1535974630,    // Expired time 
  "nbf": 1535967430,     // Do not receive and process the Token
  "sub": "www.admin.com",  // User-oriented 
  "jti": "9f10e796726e332cec401c569969e13e"  // The Token Only 1 Identification 
}

signature section:


HMACSHA256(
 base64UrlEncode(header) + "." +
 base64UrlEncode(payload),
 123456
) 

The corresponding signature is: keH6T3x1z7mmhKL1T3r9sQdAxxdzB6siemGMr_6ZOwU

The json of the finally obtained JWT is (header. payload. signature): eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ. keH6z1mmhKL113r9sQdAxxdzB6siemGMr_6ZOwU
header and payload base64UrlEncode encoding after splicing. The HS256 algorithm is signed by key (here 123456).

JWT usage flow

Initial login: The user logs in for the first time and enters the user name and Password authentication: The server takes out the user name and password from the database for authentication Generate JWT: The server side validates and generates JWT according to the information returned from the database and the preset rules Return JWT: Return JWT in the server's HTTP RESPONSE Request with JWT: After the client initiates the request, HTTP REQUEST The Authorizatio field in HEADER must have a value, which is JWT Server validation JWT

How to Implement JWT in PHP

The author uses PHP 7.0. 31. Don't talk nonsense, just put on the code, create a new jwt. php, and copy and paste it as follows:


<?php
/**
 * PHP Realization jwt
 */
class Jwt {

  // Head 
  private static $header=array(
    'alg'=>'HS256', // Generate signature Algorithm of 
    'typ'=>'JWT'  // Type 
  );

  // Use HMAC Key used when generating information summary 
  private static $key='123456';


  /**
   *  Get jwt token
   * @param array $payload jwt Load    The format is not required as follows 
   * [
   * 'iss'=>'jwt_admin', // The JWT Issuer of 
   * 'iat'=>time(), // Issue time 
   * 'exp'=>time()+7200, // Expired time 
   * 'nbf'=>time()+60, // Do not receive and process the Token
   * 'sub'=>'www.admin.com', // User-oriented 
   * 'jti'=>md5(uniqid('JWT').time()) // The Token Only 1 Identification 
   * ]
   * @return bool|string
   */
  public static function getToken(array $payload)
  {
    if(is_array($payload))
    {
      $base64header=self::base64UrlEncode(json_encode(self::$header,JSON_UNESCAPED_UNICODE));
      $base64payload=self::base64UrlEncode(json_encode($payload,JSON_UNESCAPED_UNICODE));
      $token=$base64header.'.'.$base64payload.'.'.self::signature($base64header.'.'.$base64payload,self::$key,self::$header['alg']);
      return $token;
    }else{
      return false;
    }
  }


  /**
   *  Validation token Is it valid , Default authentication exp,nbf,iat Time 
   * @param string $Token  That needs to be verified token
   * @return bool|string
   */
  public static function verifyToken(string $Token)
  {
    $tokens = explode('.', $Token);
    if (count($tokens) != 3)
      return false;

    list($base64header, $base64payload, $sign) = $tokens;

    // Get jwt Algorithm 
    $base64decodeheader = json_decode(self::base64UrlDecode($base64header), JSON_OBJECT_AS_ARRAY);
    if (empty($base64decodeheader['alg']))
      return false;

    // Signature verification 
    if (self::signature($base64header . '.' . $base64payload, self::$key, $base64decodeheader['alg']) !== $sign)
      return false;

    $payload = json_decode(self::base64UrlDecode($base64payload), JSON_OBJECT_AS_ARRAY);

    // Verification failed when the issuing time is greater than the current server time 
    if (isset($payload['iat']) && $payload['iat'] > time())
      return false;

    // Expiration time Xiaoyu current server time verification failed 
    if (isset($payload['exp']) && $payload['exp'] < time())
      return false;

    // The nbf Do not receive and process the Token
    if (isset($payload['nbf']) && $payload['nbf'] > time())
      return false;

    return $payload;
  }




  /**
   * base64UrlEncode  https://jwt.io/  Medium base64UrlEncode Coding implementation 
   * @param string $input  String to be encoded 
   * @return string
   */
  private static function base64UrlEncode(string $input)
  {
    return str_replace('=', '', strtr(base64_encode($input), '+/', '-_'));
  }

  /**
   * base64UrlEncode https://jwt.io/  Medium base64UrlEncode Decoding implementation 
   * @param string $input  String to be decoded 
   * @return bool|string
   */
  private static function base64UrlDecode(string $input)
  {
    $remainder = strlen($input) % 4;
    if ($remainder) {
      $addlen = 4 - $remainder;
      $input .= str_repeat('=', $addlen);
    }
    return base64_decode(strtr($input, '-_', '+/'));
  }

  /**
   * HMACSHA256 Signature   https://jwt.io/  Medium HMACSHA256 Signature implementation 
   * @param string $input  For base64UrlEncode(header).".".base64UrlEncode(payload)
   * @param string $key
   * @param string $alg   Algorithm mode 
   * @return mixed
   */
  private static function signature(string $input, string $key, string $alg = 'HS256')
  {
    $alg_config=array(
      'HS256'=>'sha256'
    );
    return self::base64UrlEncode(hash_hmac($alg_config[$alg], $input, $key,true));
  }
}

  // Test whether it matches official website begin
  $payload=array('sub'=>'1234567890','name'=>'John Doe','iat'=>1516239022);
  $jwt=new Jwt;
  $token=$jwt->getToken($payload);
  echo "<pre>";
  echo $token;
  
  // Right token Verify the signature 
  $getPayload=$jwt->verifyToken($token);
  echo "<br><br>";
  var_dump($getPayload);
  echo "<br><br>";
  // Test whether it matches official website end
  
  
  // Use your own test begin
  $payload_test=array('iss'=>'admin','iat'=>time(),'exp'=>time()+7200,'nbf'=>time(),'sub'=>'www.admin.com','jti'=>md5(uniqid('JWT').time()));;
  $token_test=Jwt::getToken($payload_test);
  echo "<pre>";
  echo $token_test;
  
  // Right token Verify the signature 
  $getPayload_test=Jwt::verifyToken($token_test);
  echo "<br><br>";
  var_dump($getPayload_test);
  echo "<br><br>";
  // When you use it yourself end

Related articles: