Encode decode JWT in PHP

JWT (Json Web Tokens) can be used for user authentication. They are token-based. First, you need to encode the token and send it to the client. Client will save it in his local storage or cookie. In order to decode the token, user must provide the token. Both encode and decode function on JWT wll be performed on server side in PHP.

Although I did JWT authentication with Python and Mongo DB and with Node JS and Mongo DB. But today we do it for PHP developers.

Install php-jwt

First, you need to install a library called “php-jwt”.

You can install it from composer:

COMPOSER_MEMORY_LIMIT=-1 composer require firebase/php-jwt

Or you can download and include it manually in your PHP project.

Encode JWT in PHP

When admin is logged-in, we need to generate his authentication token. First, you need to include the JWT and Key class on top of your file.

require_once "vendor/autoload.php";

use Firebase\JWT\JWT;
use Firebase\JWT\Key;

Following code will generate a JWT using ID.

$jwt_key = "your_secret_key"; // This should be consistent

$issued_at = time();

// $expiry = strtotime("+30 days");

// jwt valid for 30 days (60 seconds * 60 minutes * 24 hours * 30 days)
$expiry = $issued_at + (60 * 60 * 24 * 30);

$payload = [
    'iss' => 'https://your-website.com',
    'aud' => 'https://your-website.com',
    'iat' => $issued_at, // issued at
    'nbf' => $issued_at, //  not before
    'exp' => $expiry, // expiry time
    "id" => 1
];

$jwt = JWT::encode($payload, $jwt_key, 'HS256');
  • Here, we have set the expiry date of this token to 30 days.
  • iss: Issuer. It tells who issued this token. Usually it is a URL of the server from where the JWT is being generated.
  • aud: Audience. This tells who can use this token. By providing the URL of your website, you are telling that this token will be valid if it comes from your website only. You can also pass it as an array if you want to allow multiple audience for same token.
  • iat: It will be a timestamp in seconds since January 01, 1970 00:00:00 UTC.
  • nbf: The timestamp seconds after which the token can be used. Token provided before this time will not be accepted. We are setting it same as issued time, so you will be able to use it as soon as you generate it.
  • exp: This will be the timestamp in seconds when the token will be expired. It will also be timestamps seconds since January 01, 1970 00:00:00 UTC. We are setting it’s validity for 30 days.
  • id: Optional. This is the custom claim that we are attaching with JWT. So when we decode the token, we will get this ID. This ID can be used to check if the user still exists in the database.

Here we are using HS256 algorithm that is used for authentication in JWT. It is a combination of 2 cryptographic methods:

  1. HMAC (Hash-based Message Authentication Code)
  2. SHA-256 (Secure Hash Algorithm 256 bit)

HMAC

HMAC combines cryptographic hash function with a secret key, in this case it will be $jwt_key. It ensures that the token is not been changed and is sent from the owner of secret key (your server).

SHA-256

SHA-256 generates a 256-bit hash from any given value. It is a one-way encryption method. It means that once the hash is generated, it cannot be decrypted back to its original state. So you will not be able to see the original message once it is encrypted.

So in JWT::encode function call, we are sending our payload and secret key. We are also telling the php-jwt library to use the HS256 algorithm. It takes our payload and encrypt it with our secret key and return the hash.

You do not have to save this token in your database. Just return it as a response to AJAX request and user can save it in his local storage.

localStorage.setItem("accessToken", accessToken)

To save the token on user side, we are using localStorage web API. This will keep the access token in local storage until removed using Javascript localStorage.removeItem(“accessToken”) or if the browsing history is deleted. However, it can store only upto 10 MB. But that will be enough in this case. The token generated will be a string of just a few bytes.

It stores the data in key-value pair. In this case, our key is “accessToken” and our value is the accessToken received from server.

Note: The first parameter is a string and second is a variable.

Decode JWT in PHP

Now whenever admin sends an AJAX request, he needs to pass that access token in headers.

const ajax = new XMLHttpRequest();
ajax.open("POST", "index.php", true)

ajax.setRequestHeader("Authorization", "Bearer " + localStorage.getItem("accessToken"))

ajax.send()

Here, we are first creating an AJAX (Asynchronous JavaScript and XML) object. Then we are opening the request with method POST and the server URL is “index.php”, you can write your own route. Third parameter is async, it’s default value is also true. It means that the request will be processed asyncronously. If you use false, it will not return any value until the response is received, thus blocking the UI which is not good for user experience.

After that, we are attaching Authorization header with the AJAX request. It is a good practice to send authorization tokens in header for security and it is also a standardized way of sending tokens. So if you are developing a website or a mobile application, every developer will know that the token needs to be sent in the header.

We are using Bearer authorization token because they hide the sensitive data that we are sending in payload. Thus, even if someone reads the headers, he won’t be able to read the ID of user. And we are fetching the token value from local storage we saved earlier.

Finally, we are sending the request. If you are to send some data with the request too, you can send it in FormData object. Check our tutorial on how to send AJAX request with FormData.

Then on server side, we need to get the access token from Authorization header and decode it to see if it is valid.

// index.php

// Get the JWT from the Authorization header
try
{
    $headers = getallheaders(); // returns an array of all headers attached in this request

    if (!isset($headers['Authorization']))
    {
        echo json_encode([
            "status" => "error",
            "message" => "'authorization' header not present."
        ]);
        
        exit();
    }

    $auth_header = $headers['Authorization'];
    list($jwt) = sscanf($auth_header, "Bearer %s");

    $decoded = JWT::decode($jwt, new Key($jwt_key, 'HS256'));
    $id = $decoded->id;

    return $id;
}
catch (\Exception $exp)
{
    echo json_encode([
        "status" => "error",
        "message" => $exp->getMessage()
    ]);

    exit();
}

First, we are fetching all the headers from the request. Then we are checking if the Authorization header is present in the request. If not, then we are throwing an error. So if user fails to attach the Authorization header in the request, it will not process further.

  • sscanf: This function is used to read and parse the value from a string. While “sprintf” is used to only format the data, but this function reads the data and parses as well.
  • Our format “Bearer %s” tells the function to expecct Bearer at the start of the string. And %s tells it to put the remaining string in a variable.
  • list() is a built-in function in PHP. It is used to assign multiple values to multiple variables respectively. In this case, we are assigning value of “%s” to $jwt variable.

After that, we are decoding the token. Decode function in JWT PHP is a little different than the encode function. First parameter is the token, second is an instance of Key class from php-jwt library. It also accepts 2 parameters, first is the secret key used to generate the token and second is the algorithm used while generating the token. If there is any mismatch in token, secret key or algorithm, it will throw an exception and we will receive that in catch block.

It will return the payload that we are saving in $decoded variable. From this decoded variable, you can get the ID of the authenticated user.

That’s how you can encode and decode the JWT in PHP. If you face any problem in following this, kindly do let me know.

Login with JWT – Kotlin, Node JS, Mongo DB

In this tutorial, we will teach you how you can login a user with JWT (JSON Web Token) in the android app using Kotlin and Node JS. We will be using Node JS to generate JWT and Mongo DB to save it.

Creating an activity

First, we will create an empty activity named “LoginActivity.kt”. Following will be the code of that file:

package com.adnantech.myapp

import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle

class LoginActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_login)
    }
}

This will look for a file named “activity_login.xml” inside the “res/layout” folder.

Create an XML file

Then we will create a file named “activity_login.xml” inside the “res/layout” folder. That file will have the following code:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="20dp"
    tools:context=".LoginActivity">

    <TextView
        android:id="@+id/heading"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Login"
        android:textAlignment="center"
        android:textSize="40sp"
        android:textStyle="bold" />

    <EditText
        android:id="@+id/etPhone"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/heading"
        android:layout_marginTop="20dp"
        android:hint="Enter phone"
        android:inputType="phone" />

    <EditText
        android:id="@+id/etPassword"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/etPhone"
        android:layout_marginTop="20dp"
        android:hint="Enter password"
        android:inputType="textPassword" />

    <Button
        android:id="@+id/btnLogin"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/etPassword"
        android:layout_marginTop="20dp"
        android:text="Login" />

</RelativeLayout>

It will display the heading “Login” horizontally center-aligned. Two input fields. One to enter the phone number, and one for the password. It will also display a button that when clicked will call an HTTP request to authenticate the user.

Button onclick event listener

We need to attach an “onclick” event listener to the button. So we will create instances of all our input fields and button.

class LoginActivity : AppCompatActivity() {

    private lateinit var etPhone: EditText
    private lateinit var etPassword: EditText
    private lateinit var btnLogin: Button

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_login)

        etPhone = findViewById(R.id.etPhone)
        etPassword = findViewById(R.id.etPassword)
        btnLogin = findViewById(R.id.btnLogin)

        btnLogin.setOnClickListener {
            doLogin()
        }
    }

    private fun doLogin() {
        // [HTTP request to authenticate the user]
    }
}

And inside this button click listener, we are calling our method that will call an HTTP request.

Calling an HTTP request

To call an HTTP request, first, make sure you have INTERNET and ACCESS_NETWORK_STATE permissions added in your “AndroidManifest.xml” file.

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />

Then you need to add the following line in your “app/build.gradle” file:

implementation "com.android.volley:volley:1.2.1"

Make sure to “Gradle sync” after pasting that line. You will see the option to sync Gradle on top in Android studio. After that, you need to write the following code in the [HTTP request to authenticate the user] section:

btnLogin.isEnabled = false

val queue = Volley.newRequestQueue(this)
val url = "http://172.20.10.4:3000/login"

val requestBody =
    "phone=" + URLEncoder.encode(
        etPhone.text.toString(),
        "UTF-8"
    ) + "&password=" + etPassword.text
val stringReq: StringRequest =
    object : StringRequest(
        Method.POST, url,
        Response.Listener { response ->
            btnLogin.isEnabled = true
            Log.i("mylog", response)
        },
        Response.ErrorListener { error ->
            Log.i("myLog", "error = " + error)
        }
    ) {
        override fun getBody(): ByteArray {
            return requestBody.toByteArray(Charset.defaultCharset())
        }
    }
queue.add(stringReq)

This will first disable the login button. Then it will create an instance of Volley. After that, it sets the path of an API. You can get your IP address by running either of the following commands in your terminal:

> ipconfig /all
or
> ifconfig

You need to copy the ipv4 address and paste it as your IP address.

Then it creates a request body, the parameters that will be sent to the API. Creates an instance of “StringRequest”. When the response is received, it simply enables the login button and displays the response in the log. You can view the response by opening your “logcat” in your android studio bottom bar. And select “info” and search for “mylog”.

If you want to convert the JSON string into Kotlin class, you can check out this tutorial.

We have already created a public GitHub repo for the authentication API. You can check it out here.

So that’s how you can create a login activity in android using Kotlin with Node JS and Mongo DB as the backend. If you face any problem in following this, kindly do let me know.