Full Stack LAMP - MEAN Developer, Python developer. Certified Azure Developer. Freelance programmer/consultant/trainer.

Slim3 Framework Authorization with JWT (JSON Web Tokens)

In this post, I will show how you can secure your Slim3 Framework-based applications using JSON Web Token (JWT). To know more about JWT and How it works visit the official website(https://jwt.io).

Download & Install

We gonna use composer to download and install the Slim Framework. The easiest way to start working with Slim is to create a project using Slim-Skeleton as a base by running this bash command:

$ php composer.phar create-project slim/slim-skeleton [my-app-name]

Replace [my-app-name] with the desired directory name for your new application.

You can then run it with PHP’s built-in web server:

$ cd [my-app-name]; php -S localhost:8080 -t public public/index.php

While running built-in web server you can access the application at: http://localhost:8080. If you head over to the browser with this URL you should get following output:

Connect to database

We gonna use MySQL as a database engine, so lets open src/settings.php file and add follwing array to settings array.

        // database connection details         
        "db" => [            
             "host" => "your-host",             
             "dbname" => "your-database-name",             
             "user" => "your-db-username",            
             "pass" => "your-db-password"        

After placing your database settings, lets open src/dependencies.php file and inject database object into container with following code:

// PDO database library 
$container['db'] = function ($c) {
    $settings = $c->get('settings')['db'];
    $pdo = new PDO("mysql:host=" . $settings['host'] . ";dbname=" . $settings['dbname'],
        $settings['user'], $settings['pass']);
    return $pdo;

Now you can access this database connection instance with $this->db.

JWT Authentication

We gonna use tuupola/slim-jwt-auth library to handle JWT tokens. So let install it with composer, fire up the terminal and change the directory to project root and issue following composer command

$ composer require tuupola/slim-jwt-auth

After installation, open the src/settings.php file and append the followign JWT setttings array to existing settings array.

        // jwt settings
        "jwt" => [
            'secret' => 'supersecretkeyyoushouldnotcommittogithub'

That’s it.

Now open your src/middleware.php file and add following code.

add(new \Slim\Csrf\Guard);
$app->add(new \Tuupola\Middleware\JwtAuthentication([
    "path" => "/api", /* or ["/api", "/admin"] */
    "attribute" => "decoded_token_data",
    "secret" => "supersecretkeyyoushouldnotcommittogithub",
    "algorithm" => ["HS256"],
    "error" => function ($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));

We have configured the middleware to auth check only the URLs contains the /api. If you want to pass multiple patterns pass them in an array format.

Open your src/routes.php file and define new route for login as shown below –

use Slim\Http\Request;
use Slim\Http\Response;
use \Firebase\JWT\JWT;

$app->post('/login', function (Request $request, Response $response, array $args) {

    $input = $request->getParsedBody();
    $sql = "SELECT * FROM users WHERE email= :email";
    $sth = $this->db->prepare($sql);
    $sth->bindParam("email", $input['email']);
    $user = $sth->fetchObject();

    // verify email address.
    if(!$user) {
        return $this->response->withJson(['error' => true, 'message' => 'These credentials do not match our records.']);  

    // verify password.
    if (!password_verify($input['password'],$user->password)) {
        return $this->response->withJson(['error' => true, 'message' => 'These credentials do not match our records.']);  

    $settings = $this->get('settings'); // get settings array.
    $token = JWT::encode(['id' => $user->id, 'email' => $user->email], $settings['jwt']['secret'], "HS256");

    return $this->response->withJson(['token' => $token]);


On the successful login, it will return JWT token. This method is pretty straightforward, first, we are validating the user with email and password, if the request is valid we are generating the JWT auth token. The user has to send this token in the header(Authorization: Bearer ) in order to get access to the protected routes/URLs.

Let’s define another route, it’s not public route, you need to send Authorization token to get access to it. As I mentioned above this URL is staring with /api so the user must authenticate to access this page.

$app->group('/api', function(\Slim\App $app) {

    $app->get('/user',function(Request $request, Response $response, array $args) {

        stdClass Object
                [id] => 2
                [email] => arjunphp@gmail.com

My user table structure and its sample data:

CREATE TABLE `users` (
  `id` int(10) UNSIGNED NOT NULL,
  `first_name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `last_name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `email` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `password` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `created_at` timestamp NOT NULL DEFAULT '2019-01-25 22:11:50',
  `updated_at` timestamp NOT NULL DEFAULT '2019-01-25 22:11:50'
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

INSERT INTO `users` (`id`, `first_name`, `last_name`, `email`, `password`, `created_at`, `updated_at`) VALUES
(2, 'Arjun', 'A', 'arjunphp@gmail.com', '$2y$10$2N74YBkxYXPtEtFTxynuxeEn9OH9BZ.wI4ldZr00n1FX5q09/llbO', '2018-02-22 18:30:00', '2018-02-22 18:30:00');

  ADD UNIQUE KEY `users_email_unique` (`email`);


How to deploy slim framework on CPanel

Note: Here my encrypted password is Arjun@123

How to test

We gonna use Adanced RESt client to test apis, below are the screen shot of it.

        1. Here is my user table with one user, just import it to you database –
          CREATE TABLE `users` (
          `id` int(10) UNSIGNED NOT NULL,
          `first_name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
          `last_name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
          `email` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
          `password` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
          `created_at` timestamp NOT NULL DEFAULT ‘0000-00-00 00:00:00’,
          `updated_at` timestamp NOT NULL DEFAULT ‘0000-00-00 00:00:00’
          ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

          INSERT INTO `users` (`id`, `first_name`, `last_name`, `email`, `password`, `created_at`, `updated_at`) VALUES
          (2, ‘Arjun’, ‘A’, ‘arjunphp@gmail.com’, ‘$2y$10$2N74YBkxYXPtEtFTxynuxeEn9OH9BZ.wI4ldZr00n1FX5q09/llbO’, ‘2018-02-22 18:30:00’, ‘2018-02-22 18:30:00’);

          ALTER TABLE `users`
          ADD PRIMARY KEY (`id`),
          ADD UNIQUE KEY `users_email_unique` (`email`);

          ALTER TABLE `users`

          1. Sorry arjun. I have downloaded and tried your code but still the same error occurs.

          2. Change content type from Text to JSON in Postman request.. then you’re good to go!

          3. Thank you. It’s working and able to get token. It’s always generating same token. Need to make it to expire and regenerate new jwt. Any idea? Please share.

          4. Able to generate token now. Can you please guide me to do the following things:
            1. JWT expiration on logout (Because same jwt is generated every time, it is required to expire it and generate new jwt at every login).
            2. Front end for this sample.

  1. This article is helpful for faster developing an API,
    but i found this error

    Fatal error: Class ‘SlimMiddlewareHttpBasicAuthentication’ not found in /api/v2/jwtApi/src/middleware.php

    Why doesn’t work ?

  2. I have the login request working just fine, there were a couple things I had to modify to get it working. Downloading your files helped because I saw this was missing from my routes.php: use FirebaseJWTJWT;

    Comparing my files to yours I saw that the updated Skeleton package uses “tuupola/slim-jwt-auth”: “^3.0”, and so I had to change the middlware.php to say new TuupolaMiddlewareJwtAuthentication() instead of Slim…etc.

    I am having an issue after running and getting a login token trying to access /api/

    I get this error:

    Type: SlimExceptionContainerValueNotFoundException
    Message: Identifier “jwt” is not defined.
    File: E:Developmentnewsiteslim-skeletonvendorslimslimSlimContainer.php
    Line: 120

    #0 E:Developmentnewsiteslim-skeletonsrcroutes.php(91): SlimContainer->get(‘jwt’)
    #1 [internal function]: Closure->{closure}(Object(SlimHttpRequest), Object(SlimHttpResponse), Array)

    Any ideas? I did more file comparisons between what I have an what you had above, but saw no easy answers why it wouldn’t work.

    1. Hi you solved problem?
      i get it same problem Message: Identifier “jwt” is not defined.
      if you solved share with me your solutions
      thank you

        1. i m download full now all ready

          use SlimHttpRequest;
          use SlimHttpResponse;
          use FirebaseJWTJWT;

          but same error return me

          Slim Application Error

          The application could not run because of the following error:


          Type: SlimExceptionContainerValueNotFoundException

          Message: Identifier “jwt” is not defined.

          File: /Users/hanifeoglu/Sites/slim-framework3-jwt/vendor/slim/slim/Slim/Container.php

          Line: 120


          #0 /Users/hanifeoglu/Sites/slim-framework3-jwt/src/routes.php(40): SlimContainer->get(‘jwt’)

          #1 [internal function]: Closure->{closure}(Object(SlimHttpRequest), Object(SlimHttpResponse), Array)

          #2 /Users/hanifeoglu/Sites/slim-framework3-jwt/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponse.php(41): call_user_func(Object(Closure), Object(SlimHttpRequest), Object(SlimHttpResponse), Array)

          #3 /Users/hanifeoglu/Sites/slim-framework3-jwt/vendor/slim/slim/Slim/Route.php(335): SlimHandlersStrategiesRequestResponse->__invoke(Object(Closure), Object(SlimHttpRequest), Object(SlimHttpResponse), Array)

          #4 /Users/hanifeoglu/Sites/slim-framework3-jwt/vendor/slim/slim/Slim/MiddlewareAwareTrait.php(117): SlimRoute->__invoke(Object(SlimHttpRequest), Object(SlimHttpResponse))

          #5 /Users/hanifeoglu/Sites/slim-framework3-jwt/vendor/slim/slim/Slim/Route.php(313): SlimRoute->callMiddlewareStack(Object(SlimHttpRequest), Object(SlimHttpResponse))

          #6 /Users/hanifeoglu/Sites/slim-framework3-jwt/vendor/slim/slim/Slim/App.php(495): SlimRoute->run(Object(SlimHttpRequest), Object(SlimHttpResponse))

          #7 /Users/hanifeoglu/Sites/slim-framework3-jwt/vendor/tuupola/callable-handler/src/CallableHandler.php(34): SlimApp->__invoke(Object(SlimHttpRequest), Object(SlimHttpResponse))

          #8 /Users/hanifeoglu/Sites/slim-framework3-jwt/vendor/tuupola/slim-jwt-auth/src/JwtAuthentication.php(150): TuupolaMiddlewareCallableHandler->handle(Object(SlimHttpRequest))

          #9 /Users/hanifeoglu/Sites/slim-framework3-jwt/vendor/tuupola/callable-handler/src/DoublePassTrait.php(30): TuupolaMiddlewareJwtAuthentication->process(Object(SlimHttpRequest), Object(TuupolaMiddlewareCallableHandler))

          #10 [internal function]: TuupolaMiddlewareJwtAuthentication->__invoke(Object(SlimHttpRequest), Object(SlimHttpResponse), Object(SlimApp))

          #11 /Users/hanifeoglu/Sites/slim-framework3-jwt/vendor/slim/slim/Slim/DeferredCallable.php(43): call_user_func_array(Object(TuupolaMiddlewareJwtAuthentication), Array)

          #12 [internal function]: SlimDeferredCallable->__invoke(Object(SlimHttpRequest), Object(SlimHttpResponse), Object(SlimApp))

          #13 /Users/hanifeoglu/Sites/slim-framework3-jwt/vendor/slim/slim/Slim/MiddlewareAwareTrait.php(70): call_user_func(Object(SlimDeferredCallable), Object(SlimHttpRequest), Object(SlimHttpResponse), Object(SlimApp))

          #14 /Users/hanifeoglu/Sites/slim-framework3-jwt/vendor/slim/slim/Slim/MiddlewareAwareTrait.php(117): SlimApp->Slim{closure}(Object(SlimHttpRequest), Object(SlimHttpResponse))

          #15 /Users/hanifeoglu/Sites/slim-framework3-jwt/vendor/slim/slim/Slim/App.php(388): SlimApp->callMiddlewareStack(Object(SlimHttpRequest), Object(SlimHttpResponse))

          #16 /Users/hanifeoglu/Sites/slim-framework3-jwt/vendor/slim/slim/Slim/App.php(296): SlimApp->process(Object(SlimHttpRequest), Object(SlimHttpResponse))

          #17 /Users/hanifeoglu/Sites/slim-framework3-jwt/public/index.php(30): SlimApp->run()

          #18 {main}

  3. Fatal error: Class ‘SlimMiddlewareJwtAuthentication’ not found in
    C:xampphtdocsv2022srcroutesapi.php on line
    23 im getting this error and vendor folder is also missing…. and one more thing is is token store store in db

  4. Fatal error: Class ‘SlimMiddlewareJwtAuthentication’ not found in
    C:xampphtdocstask_managersrcroutesapi.php on line

    how resolve this issue sir can uh explain

      1. Thank you arjun, now done working i m create try again db and import .sql file now done working now i m get it token here have now problem


        Type: SlimExceptionContainerValueNotFoundException
        Message: Identifier “jwt” is not defined.
        File: /Users/salih/ws/vendor/slim/slim/Slim/Container.php
        Line: 120

          1. yes i m delete it vendor folder and run composer install try again but not sol same problem continue i thinking problem version problem

          2. i run this command composer show -i
            my installed:

            container-interop/container-interop 1.2.0 Promoting the interoperability of container objects (DIC, SL, etc.)

            doctrine/instantiator 1.1.0 A small, lightweight utility to instantiate objects in PHP without invoking their constructors

            firebase/php-jwt v5.0.0 A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current…

            http-interop/http-factory 0.3.0 Common interface for HTTP message factories

            monolog/monolog 1.23.0 Sends your logs to files, sockets, inboxes, databases and various web services

            myclabs/deep-copy 1.7.0 Create deep copies (clones) of your objects

            nikic/fast-route v1.3.0 Fast request router for PHP

            phpdocumentor/reflection-common 1.0.1 Common reflection classes used by phpdocumentor to reflect the code structure

            phpdocumentor/reflection-docblock 4.3.0 With this component, a library can provide support for annotations via DocBlocks or otherwise ret…

            phpdocumentor/type-resolver 0.4.0

            phpspec/prophecy 1.7.6 Highly opinionated mocking framework for PHP 5.3+

            phpunit/php-code-coverage 4.0.8 Library that provides collection, processing, and rendering functionality for PHP code coverage i…

            phpunit/php-file-iterator 1.4.5 FilterIterator implementation that filters files based on a list of suffixes.

            phpunit/php-text-template 1.2.1 Simple template engine.

            phpunit/php-timer 1.0.9 Utility class for timing

            phpunit/php-token-stream 2.0.2 Wrapper around PHP’s tokenizer extension.

            phpunit/phpunit 5.7.27 The PHP Unit Testing framework.

            phpunit/phpunit-mock-objects 3.4.4 Mock Object library for PHPUnit

            pimple/pimple v3.2.3 Pimple, a simple Dependency Injection Container

            psr/container 1.0.0 Common Container Interface (PHP FIG PSR-11)

            psr/http-message 1.0.1 Common interface for HTTP messages

            psr/http-server-handler 1.0.0 Common interface for HTTP server-side request handler

            psr/http-server-middleware 1.0.0 Common interface for HTTP server-side middleware

            psr/log 1.0.2 Common interface for logging libraries

            sebastian/code-unit-reverse-lookup 1.0.1 Looks up which function or method a line of code belongs to

            sebastian/comparator 1.2.4 Provides the functionality to compare PHP values for equality

            sebastian/diff 1.4.3 Diff implementation

            sebastian/environment 2.0.0 Provides functionality to handle HHVM/PHP environments

            sebastian/exporter 2.0.0 Provides the functionality to export PHP variables for visualization

            sebastian/global-state 1.1.1 Snapshotting of global state

            sebastian/object-enumerator 2.0.1 Traverses array structures and object graphs to enumerate all referenced objects

            sebastian/recursion-context 2.0.0 Provides functionality to recursively process PHP variables

            sebastian/resource-operations 1.0.0 Provides a list of PHP built-in functions that operate on resources

            sebastian/version 2.0.1 Library that helps with managing the version number of Git-hosted PHP projects

            slim/php-view 2.2.0 Render PHP view scripts into a PSR-7 Response object.

            slim/slim 3.10.0 Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications a…

            symfony/yaml v4.0.8 Symfony Yaml Component

            tuupola/callable-handler 0.3.0 Compatibility layer for PSR-7 double pass and PSR-15 middlewares.

            tuupola/http-factory 0.3.0 Lightweight autodiscovering PSR-17 HTTP factories

            tuupola/slim-jwt-auth 3.0.0 PSR-7 and PSR-15 JWT Authentication Middleware

            webmozart/assert 1.3.0 Assertions to validate method input/output with nice error messages.

  5. hi can you help me, the project generates the following error


    Type: SlimExceptionContainerValueNotFoundException
    Message: Identifier “jwt” is not defined.
    File: /home/user/public_html/slim-framework3-jwt/vendor/slim/slim/Slim/Container.php
    Line: 120

    #0 /home/user/public_html/slim-framework3-jwt/src/routes.php(40): SlimContainer->get(‘jwt’)

  6. note: sorry for my english
    SOLUTION for ‘Message: Identifier’ jwt is not defined. ‘, May not be the best or the correct solution, but for me it worked.
    instead of:
    change for:
    $settings = $this->get(‘settings’); // get settings array.
    $input = $request->getHeaders();
    $token_input = explode(” “, $input[“HTTP_AUTHORIZATION”][0]);
    $token = JWT::decode($token_input[1], $settings[‘jwt’][‘secret’], [‘HS256’]);
    return $this->response->withJson([‘token’ => $token->id . ‘ ‘ . $token->email]);

          1. Arjun,

            could you tell me how to save the token in location storage. I would like vanessa mentioned before, add the authorization header on my get api. If I want information about user this works fine in postman. But I would like to add this header automatic on the request. I saw that you mentioned to save. How and where do I have to save this token, and how should i get the token and add it to a get request.

  7. if any person get it


    “status”: “error”,

    “message”: “Signature verification failed”


    create it new password with hash this is has wrong in database

    (2, ‘Arjun’, ‘A’, ‘arjunphp@gmail.com’, ‘$2y$10$2N74YBkxYXPtEtFTxynuxeEn9OH9BZ.wI4ldZr00n1FX5q09/llbO’, ‘2018-02-22 18:30:00’, ‘2018-02-22 18:30:00’);

  8. Hi, I followed your instructions and when executing in my POSTMAN (xampp with php 7.2 and Mysql Innodb) the application gives the following error:

    Warning : Unknown: failed to open stream: No such file or directory in
    Unknown on line

    Fatal error : Unknown: Failed opening required ‘H: xampp72 htdocs slim3JWT public public / index.php’ (include_path = ‘H: xampp72 php PEAR’) in
    Unknown on line

  9. I have solved the problem of failed to open strim by doing only:
    php -S localhost: 8080 -t public

    I do ellogin ok, I copy eltoken that generates the login and then I do:

    localhost: 8080 / api / user? authorization = eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IjIiLCJlbWFpbCI6ImFyanVucGhwQGdtYWlsLmNvbSJ9.XMrHtM_mSBwCmuChSGuPbhJlwUU4mShN8a6p92EPt3k

    with the generated token and answer me:
    {“status”: “error”, “message”: “Token not found.” }

    what is the problem, try with your downloaded application and I have the same problem.
    I’m using php 7.2 and mysql innodb


  10. Hi Arjun, Can you please help me out for create logout functionality in you above code. i can’t clear jwt token from logout functionality.

  11. Hi Arjun. I followed the tutorial and I found some problems that i coud fix, but I am stucked in the last problem (the third in the following list):

    First I got this error:

    Fatal error: Class ‘TuupolaMiddlewareHttpBasicAuthentication’ not found in /home/alejandro/Services/src/middleware.php on line 7

    I solved it changing in the src/middleware.php file the line:

    $app->add(new TuupolaMiddlewareJwtAuthentication([

    for the line

    $app->add(new SlimMiddlewareJwtAuthentication([


    Fixed the before problem i got the following problem:

    Fatal error: Cannot use object of type SlimHttpResponse as array in /home/alejandro/Services/src/middleware.php on line 12

    I found in https://github.com/tuupola/slim-basic-auth#-allow-https-termination-and-forwarding that to use it with http (not https), you need to add the

    “secure” => false,


    Fixed all the before, I found the following problem:

    Fatal error: Cannot use object of type SlimHttpResponse as array in /home/alejandro/Services/src/middleware.php on line 13

    Following the file src/middleware.php

    add(new SlimCsrfGuard);
    $app->add(new SlimMiddlewareJwtAuthentication([
    “path” => “/api”, /* or [“/api”, “/admin”] */
    “attribute” => “decoded_token_data”,
    “secure” => false,
    “secret” => “supersecretkeyyoushouldnotcommittogithub”,
    “algorithm” => [“HS256”],
    “error” => function ($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));

    It seems that doesn’t like the line:
    return $response
    ->withHeader(“Content-Type”, “application/json”)
    ->write(json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));

  12. Thanks for this great tutorial. Just have a quick question?
    how can I access the $request->getAtrribute(‘decoded_token_data’) within the class constructor?

    Sample route:
    $app->group(‘/api’, function(SlimApp $app) {
    $app->get(‘/sample’, ‘HomeController:sample’);

    Something like this

    class HomeController{

    private $classToken;

    function __construct()
    $this->classToken = $request->getAtrribute(‘decoded_token_data’);


  13. I am having trouble with the password verify and I had to comment it out to get the token. Also the /api/user get function returns a null how do I fix that

  14. Hi
    How to decode JWT Response for example if a user registration form is filled in android application and it encoded as jwt .In server side how we decode this jwt and how post form field values.

    1. You don’t encode the payload into a jwt. JWT is only for authentication, a key to prove your identity. Use SSL(https) to ensure your data is encrypted and safe in transit.

Leave a Reply