firebase/php-jwt + Angular | REST API Authentication Using JSON Web Token with Guards Example Tutorial Part 2

JSON Web Tokens(JWT) are used to secure communication between client and servers. JWT is an encrypted string which is generated by the server after verification of user credentials when they log in. After that this JWT is used to verify the authenticity of the user asking for server responses. So at the server end the…

By.

min read

JSON Web Tokens(JWT) are used to secure communication between client and servers. JWT is an encrypted string which is generated by the server after verification of user credentials when they log in. After that this JWT is used to verify the authenticity of the user asking for server responses.

So at the server end the user always need to pass JWT in HTTP call’s header, which is verified/ matched to generated one on the login process.

In our previous tutorial, we implemented JWT and in our Angular application using angular2-jwt package, which makes it easy to add JWT in every HTTP call and also provide other options to manage JWT at the client end.

You can check out the previous tutorial first for Client application demo having Login and Dashboard pages, we have also used Angular Guards to protect the Dashboard page from accessing without login.

In this article, we will discuss the server-side implementation of JWT. We will generate JWT on PHP server-side code using php-jwt. This makes JWT encoding and decoding very easy for PHP server-side code.

In our client application, we have used a login HTTP call and Dashboard HTTP call to get private data.

What is php-jwt?

php-jwt is a simple PHP library, which helps to encode and decode JSON Web Tokens (JWT) in PHP, conforming to RFC 7519.

You need to download composer to install this package and its dependencies.

Install php-jwt

We will install php-jwt using Composer. It is a PHP package manager like we use NPM for JS packages.

Run the following command in the terminal window to download php-jwt package in vendor folder:

$ composer require firebase/php-jwt

Let’s implement code for that on our PHP sample api.php file.

Just create a new file api.php (or any name you like) where we will add some PHP code to Encode/ generate and Decode/ verify the JWT strings.

First, add below code in starting of api.php, to include php-jwt library:

require_once('vendor/autoload.php');
use \Firebase\JWT\JWT; 

Note: if you are facing CORS issue, then you can add the following PHP code on the start of the file to give access from any origin.

 // Allow from any origin
    if (isset($_SERVER['HTTP_ORIGIN'])) {
        header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
        header('Access-Control-Allow-Credentials: true');
        header('Access-Control-Max-Age: 86400');    // cache for 1 day
    }

    // Access-Control headers are received during OPTIONS requests
    if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {

        if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']))
            header("Access-Control-Allow-Methods: GET, POST, OPTIONS");         

        if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']))
            header("Access-Control-Allow-Headers:        {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");

        exit(0);
    }

Define Key and Algorithm

For encoding the JWT we need a secret key using which a unique string will be generated. Also, we need to define the Algorithm we are using to decode the JWT for verification.

define('SECRET_KEY','Super-Secret-Key');  // secret key can be a random string and keep in secret from anyone
define('ALGORITHM','HS256');   // Algorithm used to sign the token

Encoding/ Generate JWT

For encoding or generating JWT token we add following code:

$iat = time(); // time of token issued at
$nbf = $iat + 10; //not before in seconds
$exp = $iat + 60; // expire time of token in seconds

$token = array(
	"iss" => "http://example.org",
	"aud" => "http://example.com",
	"iat" => $iat,
	"nbf" => $nbf,
	"exp" => $exp,
	"data" => array(
			"id" => 11,
			"email" => $email
	)
);

http_response_code(200);

$jwt = JWT::encode($token, SECRET_KEY);

Here we have defined some values in $token which will be included during the encoding process for JWT. These are called claims, these values are optional but adding them makes the JWT more secure.

iat – The time when Token is generated.i.e 1536555855318.

iss – The name or identifier string value representing the issuer application. This can be a domain name which can be used to discard tokens from other applications.

nbf – The timestamp when consideration of token starts and should be equal or greater than iat( Time of token creation ). Here nbf is $iat + 10 so it is considered valid after 10 seconds of creation.

<strong>exp</strong> – The timestamp at which token stops being valid and expires. At this point, 401 unauthorized status should return from server to indicate recreation of JWT. This value should be greater than nbf.

JWT::encode method is taking two parameters, first one is claims $token object and the second one will have the secret key which we define in SECRET_KEY this will return encoded JWT token in $jwt variable which will look like this string:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9leGFtcGxlLm9yZyIsImF1ZCI6Imh0dHA6XC9cL2V4YW1wbGUuY29tIiwiaWF0IjoxNTY2NjM2MTE1LCJuYmYiOjE1NjY2MzYxMjUsImV4cCI6MTU2NjYzNjE3NSwiZGF0YSI6eyJpZCI6MTEsImVtYWlsIjoiZnJlYWt5QGpvbGx5LmNvbSJ9fQ.lt3g9SFilMfRRC8DGUX0UL5qM3it3VKW9mDgj-NzDQM

Decode/ Verify JWT

After encoding, we get JWT which we need to send to the client like we have Angular app after that client app saves the token in localStorage and send that token in HTTP call’s Authorization header. This token is decoded or verified on server end by using below decode method:

Fetch Authorization Header with Bearer token by using the below code:

	$authHeader = $_SERVER['HTTP_AUTHORIZATION'];
	$temp_header = explode(" ", $authHeader);
	$jwt = $temp_header[1];

here we used explode method to get the only token string.

to decode or verify we use following decode method:

JWT::$leeway = 10;
$decoded = JWT::decode($jwt, SECRET_KEY, array(ALGORITHM));

Here we used $leeway option, as sometimes the timing of server in different locations.

So finally after combining the encode and decode methods for our Angular application our server api.php file will look like this:

<?php

 // Allow from any origin
    if (isset($_SERVER['HTTP_ORIGIN'])) {
        header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
        header('Access-Control-Allow-Credentials: true');
        header('Access-Control-Max-Age: 86400');    // cache for 1 day
    }

    // Access-Control headers are received during OPTIONS requests
    if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {

        if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']))
            header("Access-Control-Allow-Methods: GET, POST, OPTIONS");         

        if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']))
            header("Access-Control-Allow-Headers:        {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");

        exit(0);
    }
	
	
require_once('vendor/autoload.php');
use \Firebase\JWT\JWT; 
define('SECRET_KEY','Super-Secret-Key');  // secret key can be a random string and keep in secret from anyone
define('ALGORITHM','HS256');   // Algorithm used to sign the token



$postdata = file_get_contents("php://input");
$request = json_decode($postdata);


$action = $request->action;


// Login section
if ($action == 'login') {
	
	$email = $request->email;
	$password = $request->password;	

		//A dummy credential match.. you should have some SQl queries to match from databases
		if($email == "[email protected]" && $password == "12345678")
		{
			$iat = time(); // time of token issued at
			$nbf = $iat + 10; //not before in seconds
			$exp = $iat + 60; // expire time of token in seconds

			$token = array(
				"iss" => "http://example.org",
				"aud" => "http://example.com",
				"iat" => $iat,
				"nbf" => $nbf,
				"exp" => $exp,
				"data" => array(
						"id" => 11,
						"email" => $email
				)
			);

			http_response_code(200);

			$jwt = JWT::encode($token, SECRET_KEY);
		
		
			$data_insert=array(
				'access_token' => $jwt,									
				'id'   => '007',
				'name' => 'Jolly',
				'time' => time(),
				'username' => 'FreakyJolly', 
				'email' => '[email protected]', 
				'status' => "success",
				'message' => "Successfully Logged In"
			);
			
			
		}else{
			$data_insert=array(
				"data" => "0",
				"status" => "invalid",
				"message" => "Invalid Request"
			);	
		}	

}
// Get Dashboard stuff
else if($action == 'stuff'){

	$authHeader = $_SERVER['HTTP_AUTHORIZATION'];
	$temp_header = explode(" ", $authHeader);
	$jwt = $temp_header[1];
	
    try {
		JWT::$leeway = 10;
        $decoded = JWT::decode($jwt, SECRET_KEY, array(ALGORITHM));

        // Access is granted. Add code of the operation here 

		$data_from_server = '{"Coords":[{"Accuracy":"65","Latitude":"53.277720488429026","Longitude":"-9.012038778269686","Timestamp":"Fri Jul 05 2013 11:59:34 GMT+0100 (IST)"},{"Accuracy":"65","Latitude":"53.277720488429026","Longitude":"-9.012038778269686","Timestamp":"Fri Jul 05 2013 11:59:34 GMT+0100 (IST)"},{"Accuracy":"65","Latitude":"53.27770755361785","Longitude":"-9.011979642121824","Timestamp":"Fri Jul 05 2013 12:02:09 GMT+0100 (IST)"},{"Accuracy":"65","Latitude":"53.27769091555766","Longitude":"-9.012051410095722","Timestamp":"Fri Jul 05 2013 12:02:17 GMT+0100 (IST)"},{"Accuracy":"65","Latitude":"53.27769091555766","Longitude":"-9.012051410095722","Timestamp":"Fri Jul 05 2013 12:02:17 GMT+0100 (IST)"}]}';
		
		
		$data_insert=array(
			"data" => json_decode($data_from_server),
			"status" => "success",
			"message" => "Request authorized"
		);	

    }catch (Exception $e){

		http_response_code(401);

		$data_insert=array(
			//"data" => $data_from_server,
			"jwt" => $jwt,
			"status" => "error",
			"message" => $e->getMessage()
		);
		
	}	
}

echo json_encode($data_insert);
?>

This is a demo version of a server PHP file to demonstrate how to use PHP-jwt, with no actual password hashing or MySQL queries and database connection.

You can visit our previous post to see the Angular application(Part 1) and apply server code on this post.

 

 

 

2 responses to “firebase/php-jwt + Angular | REST API Authentication Using JSON Web Token with Guards Example Tutorial Part 2”

  1. er Avatar

    helpful

  2. Maunank Shah Avatar
    Maunank Shah

    Thanks a lot…It Really helped me a lot

Leave a Reply

Your email address will not be published. Required fields are marked *