Home IT Authenticating users with JWT

Authenticating users with JWT

Author

Date

Category

Let’s say we have an application that you want to be stateless. You research trough the web and you find that JWT is a good solution for your case. It can contain the user’s identity and additional information, that your service or application could benefit.

You’ll need the following in order to tag along with the article:

Project setup

Go to your projects folder (or any folder you want to keep your code in), open a terminal there and clone the repo and go to the server-setup branch.

git clone https://github.com/IvanMilanov/authenticating-users-with-jwt.git
cd authenticating-users-with-jwt
git checkout server-setup

At this point, you should have the files copied and you can run the following command in order to start your server:

docker-compose up

This will bring up a server running on http://localhost:8000 and you should see the Hello world! message. This is your first endpoint, that will be publicly accessible.

Then you’ll need to initiate the composer.json file in order to bring up dependencies to your project (external packages)

composer init

You can just skip the prompted information by hitting enter. It’s not that important for now. You’ll need a package, so you don’t have to do all the work by yourself. I recommend using the firebase/jwt-php package, but you can checkout what’s available and choose another if this doesn’t suite you. Install it with the following command:

composer require firebase/php-jwt

Creating the authentication endpoint

The first step is to have an endpoint, where you can issue a token. You give it username (or email) and password and you get a token with the user’s id and name for example.

Create login.php file under the public folder and paste there the following code

<?php
// require the autoload.php file, that will take care for requiring all packages for you
require '../vendor/autoload.php';

// we're going to use the JWT class from the Firebase package
use \Firebase\JWT\JWT;

// set all the user's data (usually this comes from database)
$user = [
    'id' => 123456,
    'username' => 'johndoe',
    'password' => 'secret',
    'name' => 'John Doe'
];

// don't proceed if the username and password are not sent at all
if (!isset($_POST['username']) || !isset($_POST['password'])) {
    header('HTTP/1.0 401 Unauthorized');
    echo 'Username and password are required in order to get token!';
    exit;
}

// don't proceed if the username and password doesn't match
if ($_POST['username'] !== $user['username'] || $_POST['password'] !== $user['password']) {
    header('HTTP/1.0 401 Unauthorized');
    echo 'Username or password are invalid!';
    exit;
}

// set the encryption key
$key = "example_key";

// set the JWT's payload
$payload = array(
    "iss" => "http://example.org",
    "aud" => "http://example.com",
    "iat" => 1356999524,
    "nbf" => 1357000000,
    "sub" => $user['id'],
    "name" => $user['name']
);

// return the generated JWT to the client
echo JWT::encode($payload, $key);

As you can see, every block of code has comments that begin with // which will tell you what is happening there. It’s a good practice to document your code, so you know what’s happening there.

Now you can test out what you just created by calling the endpoint with Postman. As you can see, I’ve selected a POST request to the http://localhost:8000/login.php endpoint. Then in Body select form-data and create the username and password keys with the values that you used in the $user‘s array. You should see a generated JWT as response if everything went as planned.

Congratulations, you’ve just created your first JWT. Let’s put it into use.

Creating the protected endpoint

Again in the public directory create protected.php file with the following content:

<?php
require '../vendor/autoload.php';

use \Firebase\JWT\JWT;

// we verify that the request has authorization header
if (!isset($_SERVER['HTTP_AUTHORIZATION'])) {
    header('HTTP/1.0 401 Unauthorized');
    echo 'Unauthorized!';
    exit;
}

// get the authorisation token from the request
$jwt = str_replace('Bearer ', '', $_SERVER['HTTP_AUTHORIZATION']);

// set the key
$key = "example_key";

// decode the token and return Unauthorized if something goes wrong (invalid token for example)
try {
    $decoded = JWT::decode($jwt, $key, array('HS256'));
} catch (\Exception $exception) {
    header('HTTP/1.0 401 Unauthorized');
    echo 'Unauthorized!';
    exit;
}

// send response
echo 'Hello ' . $decoded->name . ' with ID:' . $decoded->sub;

Next, you can call your protected data with the token, that you’ve created in the previous endpoint.

As you can see, I’ve selected a GET request on the http://localhost:8000/protected.php endpoint. After that, we should pass the token with the request, so we select the Authorization tab, then for the TYPE, select Bearer Token and paste the token in the field. Then hit Send and see your data appear.

You can try to call this endpoint without token or even if you change one symbol in the current token, you’ll get Unauthoried response.

Next steps

You can go further with this project and create your own database with users and authenticate them.

You can store the secret in a config or .env file.

The code is available here https://github.com/IvanMilanov/authenticating-users-with-jwt/

Checkout server-setup to get only the empty project with a working server (as you maybe did at the beginning of this article)

Checkout jwt-implementation to see the final solution

Previous articleIntroduction to JWT

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Ivan Milanov

Full stack developer

I'm a software developer from Bulgaria. In my daily work I stumble across many issues, some of which I'm going to talk about in this website.

Recent posts

Authenticating users with JWT

Let's say we have an application that you want to be stateless. You research trough the web and you find that JWT...

Introduction to JWT

The JSON Web Token is simple, but powerful authentication method even though the size is relatively small. It contains the identity of...

Recent comments