# Auth Middleware in Slim 4

**URL:** https://discourse.slimframework.com/t/auth-middleware-in-slim-4/4179
**Category:** Questions
**Created:** [May 19, 2020, 4:25pm UTC](https://discourse.slimframework.com/t/auth-middleware-in-slim-4/4179 "2020-05-19T16:25:29Z")
**Posts on this page:** 10
**Page:** 1

<div class="post-metadata">

### Author: ![Vino](https://avatars.discourse-cdn.com/v4/letter/v/c2a13f/32.png) [@Vino](https://discourse.slimframework.com/u/Vino)
#### Post date: [May 19, 2020, 4:25pm UTC](https://discourse.slimframework.com/t/auth-middleware-in-slim-4/4179/1 "2020-05-19T16:25:29Z")

</div>

Hi All,

Request your help, the below settings errors out “Call to a member function getName() on null” , so tried to reorder the sequence of the middleware as below, still no luck

**Tried - Not working**

```auto
$app->add($LoginauthMiddleware);
$app->addRoutingMiddleware();

```

**Tried - Not working**

```auto
$app->addRoutingMiddleware();
$app->add($LoginauthMiddleware);

```

**Code**

```auto
use DI\Container;
use Slim\Factory\AppFactory;
use Slim\Views\Twig;
use Slim\Views\TwigMiddleware;
use Slim\Exception\NotFoundException;
use Slim\Exception\HttpNotFoundException;
use Slim\Routing\RouteCollectorProxy;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
use Selective\BasePath\BasePathDetector;
use Selective\BasePath\BasePathMiddleware;
require '../Slim4/vendor/autoload.php';

$container = new Container();
AppFactory::setContainer($container);
$container->set('view', function() { return Twig::create('../tpl', ['cache' => false]); });
$app = AppFactory::create();

$LoginauthMiddleware = function($request, $handler): ResponseInterface {
    $route = $request->getAttribute('route');
    $routeName = $route->getName();
    $groups = $route->getGroups();
    $publicRoutesArray = array('login', 'allow');
    if(empty($_SESSION['user']) && (!in_array($routeName, $publicRoutesArray))) {
       return $response->withRedirect(ROOT_PATH.'login');
    } else { $response = $handler->handle($request); }
    return $response;
};
$app->add($LoginauthMiddleware);
$app->addRoutingMiddleware();
$basePath = (new BasePathDetector($_SERVER))->getBasePath();
$app->setBasePath($basePath);
$app->add(TwigMiddleware::createFromContainer($app));
$app->addErrorMiddleware(true, true, true);

```

---

<div class="post-metadata">

### Author: ![odan](https://avatars.discourse-cdn.com/v4/letter/o/9de053/32.png) [@odan](https://discourse.slimframework.com/u/odan)
#### Post date: [May 19, 2020, 5:17pm UTC](https://discourse.slimframework.com/t/auth-middleware-in-slim-4/4179/2 "2020-05-19T17:17:14Z")

</div>

Hi @Vino I see at least 2 or 3 issue in this codebase.

1. The container is not fully initialized. Better create the PHP-DI container with the ContainerBuilder.

2. Use RouteContext to retrieving the current route.

3. A last tip: Use the the `BasePathMiddleware` as decribed [here](https://github.com/selective-php/basepath#slim-4-integration).

---

<div class="post-metadata">

### Author: ![Vino](https://avatars.discourse-cdn.com/v4/letter/v/c2a13f/32.png) [@Vino](https://discourse.slimframework.com/u/Vino)
#### Post date: [May 19, 2020, 6:11pm UTC](https://discourse.slimframework.com/t/auth-middleware-in-slim-4/4179/3 "2020-05-19T18:11:43Z")

</div>

Hi Odan,

Thank you very much, I have followed all your step’s as below, please correct me if ou find anything incorrect and now the earlier errors got resolved, and now a new error is occurring.

**Error : Call to a member function withRedirect() on null**  
**Code**

```auto
use DI\Container;
use Slim\Factory\AppFactory;
use Slim\Views\Twig;
use Slim\Views\TwigMiddleware;
use Slim\Exception\NotFoundException;
use Slim\Exception\HttpNotFoundException;
use Slim\Routing\RouteCollectorProxy;
use Slim\Routing\RouteContext;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
use Selective\BasePath\BasePathDetector;
use Selective\BasePath\BasePathMiddleware;
require '../Slim4/vendor/autoload.php';

$builder = new DI\ContainerBuilder();
$container = $builder->build();
AppFactory::setContainer($container);
$container->set('view', function() { return Twig::create('../tpl', ['cache' => false]); });
$app = AppFactory::create();

$LoginauthMiddleware = function($request, $handler): ResponseInterface {
    $routeContext = RouteContext::fromRequest($request);
    $route = $routeContext->getRoute();
    if(empty($route)) { throw new NotFoundException($request, $response); }
    $routeName = $route->getName();
    $groups = $route->getGroups();
    $methods = $route->getMethods();
    $arguments = $route->getArguments();
    $publicRoutesArray = array('login', 'allow');
    if(empty($_SESSION['user']) && (!in_array($routeName, $publicRoutesArray))) {
       header("HTTP/1.1 302 Found");
       return $response->withRedirect('login');
    } else { $response = $handler->handle($request); }
    return $response;
};
$app->add($LoginauthMiddleware);
$app->addRoutingMiddleware();
$app->add(new BasePathMiddleware($app));
$app->add(TwigMiddleware::createFromContainer($app));
$app->addErrorMiddleware(true, true, true);

$app->get('/login', function($request, $response) use($app) {
      return $this->get('view')->render($response, 'page_login.html');
})->setName('login');

```

---

<div class="post-metadata">

### Author: ![odan](https://avatars.discourse-cdn.com/v4/letter/o/9de053/32.png) [@odan](https://discourse.slimframework.com/u/odan)
#### Post date: [May 19, 2020, 7:29pm UTC](https://discourse.slimframework.com/t/auth-middleware-in-slim-4/4179/4 "2020-05-19T19:29:47Z")

</div>

Ok, now it’s better 🙂

You may check the Slim 4 documentation:

- [http://www.slimframework.com/docs/v4/objects/response.html#returning-a-redirect](http://www.slimframework.com/docs/v4/objects/response.html#returning-a-redirect)
- [http://www.slimframework.com/docs/v4/objects/routing.html#route-names](http://www.slimframework.com/docs/v4/objects/routing.html#route-names)

```php
use Slim\Routing\RouteContext;

// Create a redirect for a named route
$routeParser = RouteContext::fromRequest($request)->getRouteParser();
$url = $routeParser->urlFor('login');

return $response->withHeader('Location', $url)->withStatus(302);

```

---

<div class="post-metadata">

### Author: ![Vino](https://avatars.discourse-cdn.com/v4/letter/v/c2a13f/32.png) [@Vino](https://discourse.slimframework.com/u/Vino)
#### Post date: [May 20, 2020, 7:45am UTC](https://discourse.slimframework.com/t/auth-middleware-in-slim-4/4179/5 "2020-05-20T07:45:29Z")

</div>

Hi Odan,

Still no luck, and error out with “Call to a member function withHeader() on null”.

**Code**

```auto
use DI\Container;
use Slim\Factory\AppFactory;
use Slim\Views\Twig;
use Slim\Views\TwigMiddleware;
use Slim\Exception\NotFoundException;
use Slim\Routing\RouteContext;
use Slim\Routing\RouteCollectorProxy;
use Slim\Routing\RouteContext;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
use Selective\BasePath\BasePathDetector;
use Selective\BasePath\BasePathMiddleware;
require '../Slim4/vendor/autoload.php';

$builder = new DI\ContainerBuilder();
$container = $builder->build();
AppFactory::setContainer($container);
$container->set('view', function() { return Twig::create('../tpl', ['cache' => false]); });
$app = AppFactory::create();

$LoginauthMiddleware = function($request, $handler): ResponseInterface {
    $routeContext = RouteContext::fromRequest($request);
    $route = $routeContext->getRoute();
    if(empty($route)) { throw new NotFoundException($request, $response); }
    $routeName = $route->getName();
    $groups = $route->getGroups();
    $methods = $route->getMethods();
    $arguments = $route->getArguments();
    $publicRoutesArray = array('login');
    if(empty($_SESSION['user']) && (!in_array($routeName, $publicRoutesArray))) {
       $routeParser = RouteContext::fromRequest($request)->getRouteParser();
	   $url = $routeParser->urlFor('login');
       return $response->withHeader('Location', $url)->withStatus(302);
    } else { $response = $handler->handle($request); }
    return $response;
};
$app->add($LoginauthMiddleware);
$app->addRoutingMiddleware();
$app->add(new BasePathMiddleware($app));
$app->add(TwigMiddleware::createFromContainer($app));
$app->addErrorMiddleware(true, true, true);

$app->get('/login', function($request, $response) use($app) {
      return $this->get('view')->render($response, 'page_login.html');
})->setName('login');

$app->get('/dashboard', function($request, $response) use($app) {
      return $this->get('view')->render($response, 'page_dashboard.html');
})->setName('dashboard');

```

---

<div class="post-metadata">

### Author: ![odan](https://avatars.discourse-cdn.com/v4/letter/o/9de053/32.png) [@odan](https://discourse.slimframework.com/u/odan)
#### Post date: [May 20, 2020, 8:07am UTC](https://discourse.slimframework.com/t/auth-middleware-in-slim-4/4179/6 "2020-05-20T08:07:36Z")

</div>

In a middleware you don’t get the $response from the method as parameter.

You have 3 options the retrieve or create the response:

Option 1 (default): Invoke the handle method: `$response = $handler->handle($request);`  
Option 2: Create it manually: `$response = new \Slim\Psr7\Response();`  
Option 3: Use the ResponseFactory.

```php
$responseFactory = new \Slim\Psr7\Factory\ResponseFactory();
$response = $responseFactory->createResponse(200);

```

The correct method / usage depends on the specific functionality and context of the middleware.

Please read the documentation: [https://www.slimframework.com/docs/v4/concepts/middleware.html](https://www.slimframework.com/docs/v4/concepts/middleware.html)

---

<div class="post-metadata">

### Author: ![Vino](https://avatars.discourse-cdn.com/v4/letter/v/c2a13f/32.png) [@Vino](https://discourse.slimframework.com/u/Vino)
#### Post date: [May 20, 2020, 3:50pm UTC](https://discourse.slimframework.com/t/auth-middleware-in-slim-4/4179/7 "2020-05-20T15:50:46Z")

</div>

Hi Odan,

We Tried the option 1 and 3 , below is the code and the result(Output), request your help on the same.

**Config Files**

```auto
use DI\Container;
use Slim\Factory\AppFactory;
use Slim\Views\Twig;
use Slim\Views\TwigMiddleware;
use Slim\Exception\NotFoundException;
use Slim\Routing\RouteCollectorProxy;
use Slim\Routing\RouteContext;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
use Nyholm\Psr7\Factory\Psr17Factory;
use Selective\BasePath\BasePathDetector;
use Selective\BasePath\BasePathMiddleware;

```

**Option 1: Closure middleware example**  
**Output : Does not authendicate,when visiting the url “htttps://abc.com/dashboard” rather it directly display the page**

```auto
$beforeMiddleware = function($request, $handler) {
    $routeContext = RouteContext::fromRequest($request);
    $route = $routeContext->getRoute();
    if(empty($route)) { throw new NotFoundException($request, $response); }
    $routeName = $route->getName();
    $publicRoutesArray = array('login','dashboard');
    if(empty($_SESSION['user']) && (in_array($routeName, $publicRoutesArray))) {
       $routeParser = RouteContext::fromRequest($request)->getRouteParser();
       $url = $routeParser->urlFor('login');
       $response = $handler->handle($request);
       return $response->withHeader('Location', $url)->withStatus(302);
    } else { $response = $handler->handle($request); }
    return $response;
};
$app->add($beforeMiddleware);

```

**Option 1: Invokable class middleware example**  
**Output : Does not authendicate,when visiting the url “htttps://abc.com/dashboard” rather it directly display the page**

```auto
class beforeMiddleware {

 public function __invoke($request, $handler): Response {
    $routeContext = RouteContext::fromRequest($request);
    $route = $routeContext->getRoute();
    if(empty($route)) { throw new NotFoundException($request, $response); }
    $routeName = $route->getName();
    $publicRoutesArray = array('login','dashboard');
    if(empty($_SESSION['user']) && (in_array($routeName, $publicRoutesArray))) {
       $routeParser = RouteContext::fromRequest($request)->getRouteParser();
       $url = $routeParser->urlFor('login');
       $response = $handler->handle($request);
       return $response->withHeader('Location', $url)->withStatus(302);
    } else { $response = $handler->handle($request); }
    return $response;
 }
}
$app->add(new beforeMiddleware());

```

**Option 3: Closure middleware example - Response Factory**  
**Output : Empty Page, No errors in the log**

```auto
$beforeMiddleware = function ($request, $handler) {
    $routeContext = RouteContext::fromRequest($request);
    $route = $routeContext->getRoute();
    if(empty($route)) { throw new NotFoundException($request, $response); }
    $routeName = $route->getName();
    $groups = $route->getGroups();
    $methods = $route->getMethods();
    $arguments = $route->getArguments();
    $publicRoutesArray = array('login','dashboard');
    if(empty($_SESSION['user']) && (in_array($routeName, $publicRoutesArray))) {
       $routeParser = RouteContext::fromRequest($request)->getRouteParser();
       $url = $routeParser->urlFor('login');
       $response = $handler->handle($request);
       $responseFactory = new \Nyholm\Psr7\Factory\Psr17Factory();
       $response = $responseFactory->createResponse(200);
       return $response->withHeader('Location', $url)->withStatus(302);
    } else { $response = $handler->handle($request); }
    return $response;
};
$app->add($beforeMiddleware);

```

**Option 3 :Invokable class middleware example - Response Factory**  
**Output : Empty Page, No errors in the log**

```auto
class beforeMiddleware {

 public function __invoke($request, $handler): Response {
    $routeContext = RouteContext::fromRequest($request);
    $route = $routeContext->getRoute();
    if(empty($route)) { throw new NotFoundException($request, $response); }
    $routeName = $route->getName();
    $publicRoutesArray = array('login','dashboard');
    if(empty($_SESSION['user']) && (in_array($routeName, $publicRoutesArray))) {
       $routeParser = RouteContext::fromRequest($request)->getRouteParser();
       $url = $routeParser->urlFor('login');
       $response = $handler->handle($request);
       $responseFactory = new \Nyholm\Psr7\Factory\Psr17Factory();
       $response = $responseFactory->createResponse(200);
       return $response->withHeader('Location', $url)->withStatus(302);
    } else { $response = $handler->handle($request); }
    return $response;
 }
}
$app->add(new beforeMiddleware());

```

---

<div class="post-metadata">

### Author: ![Vino](https://avatars.discourse-cdn.com/v4/letter/v/c2a13f/32.png) [@Vino](https://discourse.slimframework.com/u/Vino)
#### Post date: [May 21, 2020, 7:51am UTC](https://discourse.slimframework.com/t/auth-middleware-in-slim-4/4179/8 "2020-05-21T07:51:46Z")

</div>

Hi Odan,

We are getting the below error with the below code, we have removed the base path middle ware , because in one of your doc provided in this url “**[https://odan.github.io/2019/11/05/slim4-tutorial.html#routing-setup](https://odan.github.io/2019/11/05/slim4-tutorial.html#routing-setup)**” is states that we have to set base path nor use base path middle ware only if we are running the project within a sub directory under the folder /public where as in our setup we have our project above the folder /public and the folder /public contains only index.php and we have configured our project structure as same as defined in the url doc and we get this error only wen we visit the route(/require) which we require to be authenticated, rest of the routes are working perfectly without any error.

**Error**

```auto
Got error 'PHP message: 404 Not Found\n
Type: Slim\\Exception\\HttpNotFoundException\n
Code: 404\n
Message: Not found.\n
File: /Project/test/web/Slim4/vendor/slim/slim/Slim/Middleware/RoutingMiddleware.php\n
Line: 93\n
Trace: #0 /Project/test/web/Slim4/vendor/slim/slim/Slim/Middleware/RoutingMiddleware.php(59): 
Slim\\Middleware\\RoutingMiddleware->performRouting(Object(Nyholm\\Psr7\\ServerRequest))\n
#1 /Project/test/web/Slim4/vendor/slim/slim/Slim/MiddlewareDispatcher.php(140): Slim\\Middleware\\RoutingMiddleware->process(Object(Nyholm\\Psr7\\ServerRequest), Object(class@anonymous))\n
#2 /Project/test/web/Slim4/vendor/slim/twig-view/src/TwigMiddleware.php(125): class@anonymous->handle(Object(Nyholm\\Psr7\\ServerRequest))\n
#3 /Project/test/web/Slim4/vendor/slim/slim/Slim/MiddlewareDispatcher.php(140): Slim\\Views\\TwigMiddleware->process(Object(Nyholm\\Psr7\\ServerRequest), Object(class@anonymous))\n
#4 /Project/test/web/Slim4/vendor/slim...\n'

```

**Code**

```auto
class authorization {
      public function __invoke($request, $handler): Response {
                      $routeContext = RouteContext::fromRequest($request);
                      $route = $routeContext->getRoute();
                      if(empty($route)) { throw new NotFoundException($request, $response); }
                      $routeName = $route->getName();
                      $publicRoutesArray = array('require');
                      if(empty($_SESSION['user']) && (in_array($routeName, $publicRoutesArray))) {
                         $routeParser = RouteContext::fromRequest($request)->getRouteParser();
                         $url = $routeParser->urlFor('login');
                         $response = $handler->handle($request);
                         $responseFactory = new \Nyholm\Psr7\Factory\Psr17Factory();
                         $response = $responseFactory->createResponse(200);
                         return $response->withHeader('Location', $url)->withStatus(302);
                      } else { $response = $handler->handle($request); }
             return $response;
      }
}

```

---

<div class="post-metadata">

### Author: ![odan](https://avatars.discourse-cdn.com/v4/letter/o/9de053/32.png) [@odan](https://discourse.slimframework.com/u/odan)
#### Post date: [May 21, 2020, 9:02am UTC](https://discourse.slimframework.com/t/auth-middleware-in-slim-4/4179/9 "2020-05-21T09:02:13Z")

</div>

No, this is not the correct interpretation.

For security reasons you should always place your front-controller (index.php) into the `public/` directory.

With sub-directory I don’t mean the `public/` directory. In this context “sub-directory” means a subdirectory of the project. For example when you place your app not directly under the webservers RootDirectory.

> **[Slim 4 - Tutorial](https://odan.github.io/2019/11/05/slim4-tutorial.html#i-get-a-404-not-found-error)**
>
> This tutorial shows you how to work with the powerful and lightweight Slim 4 framework.

Second. Why do you overwrite the response object here??? This makes no sense.  
Choose one of the options, but not two at the same time.

```auto
$response = $handler->handle($request);
$responseFactory = new \Nyholm\Psr7\Factory\Psr17Factory();
$response = $responseFactory->createResponse(200);

```

If you read the documentation and my answers carefully you might find a solution. That’s all I can help you with.

---

<div class="post-metadata">

### Author: ![Vino](https://avatars.discourse-cdn.com/v4/letter/v/c2a13f/32.png) [@Vino](https://discourse.slimframework.com/u/Vino)
#### Post date: [May 21, 2020, 11:26am UTC](https://discourse.slimframework.com/t/auth-middleware-in-slim-4/4179/10 "2020-05-21T11:26:17Z")

</div>

Hi Odan,

Thank you very much, we tried the below

- Removing the line “$response = $handler-\>handle($request);” and tried with other 2 lines no luck - Blank page - Slim\Exception\HttpNotFoundException \n Code: 404
- Vice versa too, still no luck - Blank page - Slim\Exception\HttpNotFoundException \n Code: 404
- Added the base path middle ware for both the test.

At last option can you please check whether the placement of “.htaccess” file is correct, based on the below setup.

```auto
/var/www/test
  .htaccess
  Smil4
     	composer.json composer.lock source vendor
  config
  public
    	.htaccess index.php
  template
  temp

```

**middleware.php**

```auto
<?php

use Selective\Config\Configuration;
use Slim\App;
use Slim\Middleware\ErrorMiddleware;
use Slim\Views\TwigMiddleware;
use Slim\Middleware\RoutingMiddleware;
use Selective\BasePath\BasePathMiddleware;

require_once('bpauthurization.php');

return function (App $app) {
       $routingMiddleware = new Slim\Middleware\RoutingMiddleware(
                $app->getRouteResolver(),
                $app->getRouteCollector()->getRouteParser()
       );
       $app->add(new authorization());
       $app->addBodyParsingMiddleware();
       $app->addMiddleware($routingMiddleware);
       $app->add(new BasePathMiddleware($app));
       $app->add(TwigMiddleware::createFromContainer($app));
       $app->add(ErrorMiddleware::class);
};
?>

```

**authorization.php**

```auto
<?php
use Slim\Routing\RouteContext;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
use Slim\Exception\NotFoundException;
use Nyholm\Psr7\Factory\Psr17Factory;
class authorization {
      public function __invoke($request, $handler): Response {
                      $routeContext = RouteContext::fromRequest($request);
                      $route = $routeContext->getRoute();
                      if(empty($route)) { throw new NotFoundException($request, $response); }
                      $routeName = $route->getName();
                      $publicRoutesArray = array('f401');
                      if(empty($_SESSION['user']) && (in_array($routeName, $publicRoutesArray))) {
                         $routeParser = RouteContext::fromRequest($request)->getRouteParser();
                         $url = $routeParser->urlFor('login');
                         $responseFactory = new \Nyholm\Psr7\Factory\Psr17Factory();
                         $response = $responseFactory->createResponse(200);
                         return $response->withHeader('Location', $url)->withStatus(302);
                      } else { $response = $handler->handle($request); }
             return $response;
      }
}

```
