Secure web services using JWT and Slim Framework

Slim framework is used to create REST API. If you want to learn how to create web services using slim please follow my this post Web services using Slim framework. In this post, I will explain how to make your REST API secure using JSON Web Token (JWT). There is lots of information already on the web about JSON Web Token (JWT) Authentication so we will not duplicate it here but in a nutshell, it allows authenticating users against a single token instead of the more commonly used username/password. You can simply follow below step to create REST API with Slim.

Install Slim framework using composer and run bellow command

php composer.phar create-project slim/slim-skeleton jwtApp

Install required dependencies

composer require firebase/php-jwt
composer require tuupola/base62
composer require tuupola/slim-basic-auth
composer require tuupola/slim-jwt-auth
composer require tuupola/cors-middleware

If you are using Apache web server you need to update into your project .htaccess file or you simply replace your .htaccess code with below code

RewriteEngine On
#RewriteBase /api/
RewriteRule .* — [env=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [QSA,L]
# Make sure $HTTP_RAW_POST_DATA is deprecated warning does not appear
php_value always_populate_raw_post_data -1

Now edit your middleware.php file inside src folder and add bellow code in it. Below code contain routes which we can access from our REST Client.

<?php
// Application middleware
// e.g: $app->add(new \Slim\Csrf\Guard);
// Adding dependencies
use Tuupola\Middleware\HttpBasicAuthentication;
$container = $app->getContainer();
$container[‘logger’] = function($c) {
 $logger = new \Monolog\Logger(‘my_logger’);
 $file_handler = new \Monolog\Handler\StreamHandler(“../logs/app.log”);
 $logger->pushHandler($file_handler);
 return $logger;
};
$container[“jwt”] = function ($container) {
 return new StdClass;
};
$app->add(new \Slim\Middleware\JwtAuthentication([
 “path” => “/”,
 “logger” => $container[‘logger’],
 “secret” => “123456789helo_secret”,
 “rules” => [
 new \Slim\Middleware\JwtAuthentication\RequestPathRule([
 “path” => “/”,
 “passthrough” => [“/token”, “/not-secure”, “/home”]
 ]),
 new \Slim\Middleware\JwtAuthentication\RequestMethodRule([
 “passthrough” => [“OPTIONS”]
 ]),
 ],
 “callback” => function ($request, $response, $arguments) use ($container) {
 $container[“jwt”] = $arguments[“decoded”];
 },
 “error” => function ($request, $response, $arguments) {
 $data[“status”] = “error”;
 $data[“message”] = $arguments[“message”];
 return $response
 ->withHeader(“Content-Type”, “application/json”)
 ->write(json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
 }
]));

After this open routes.php file and add below code.

<?php
// Routes
use Firebase\JWT\JWT;
use Tuupola\Base62;
$app->post(“/token”, function ($request, $response, $args) use ($container){
 /* Here generate and return JWT to the client. */
 //$valid_scopes = [“read”, “write”, “delete”]
$requested_scopes = $request->getParsedBody() ?: [];
$now = new DateTime();
 $future = new DateTime(“+10 minutes”);
 $server = $request->getServerParams();
 $jti = (new Base62)->encode(random_bytes(16));
 $payload = [
 “iat” => $now->getTimeStamp(),
 “exp” => $future->getTimeStamp(),
 “jti” => $jti,
 “sub” => $server[“PHP_AUTH_USER”]
 ];
 $secret = “123456789helo_secret”;
 $token = JWT::encode($payload, $secret, “HS256”);
 $data[“token”] = $token;
 $data[“expires”] = $future->getTimeStamp();
 return $response->withStatus(201)
 ->withHeader(“Content-Type”, “application/json”)
 ->write(json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
});
$app->get(“/secure”, function ($request, $response, $args) {
$data = [“status” => 1, ‘msg’ => “This route is secure!”];
return $response->withStatus(200)
 ->withHeader(“Content-Type”, “application/json”)
 ->write(json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
});
$app->get(“/not-secure”, function ($request, $response, $args) {
$data = [“status” => 1, ‘msg’ => “No need of token to access me”];
return $response->withStatus(200)
 ->withHeader(“Content-Type”, “application/json”)
 ->write(json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
});
$app->post(“/formData”, function ($request, $response, $args) {
 $data = $request->getParsedBody();
$result = [“status” => 1, ‘msg’ => $data];
// Request with status response
 return $this->response->withJson($result, 200);
});
$app->get(‘/home’, function ($request, $response, $args) {
 // Sample log message
 $this->logger->info(“Slim-Skeleton ‘/’ route”);
// Render index view
 return $this->renderer->render($response, ‘index.phtml’, [“name” => “Welcome to Trinity Tuts demo Api”]);
});

If you wan’t to read complete tutorial please please check this link:- Secure PHP Web Services using JWT.

Demo Api link :- https://demo.trinitytuts.com/api/

Video:- https://youtu.be/5tQmN7_syFA