How to use Middleware to control auth flow


#1

The slim documentation says:

The only hard requirement is that a middleware MUST return an instance of \Psr\Http\Message\ResponseInterface

The example code shows prefixing and postfixing a message to the response body

<?php
$app = new \Slim\App();

$app->add(function ($request, $response, $next) {
	$response->getBody()->write('BEFORE');
	$response = $next($request, $response);
	$response->getBody()->write('AFTER');

	return $response;
});

$app->get('/', function ($request, $response, $args) {
	$response->getBody()->write(' Hello ');

	return $response;
});

$app->run();

Given the the response object must be returned, how would you go about implementing a middleware component to prevent the Hello being displayed from the home page route above.

For example, let’s say I have a route /resource and I want to ensure that only consumers who have a ‘correct’ Authentication: header set can reach the resource, I could put a check in the middleware.

What is not clear to me is how the middleware signals to the main app->get function that authentication has failed and not to display the resource. Presumably, the middleware can’t break the call chain as its contract says “MUST” return a response.


#2

Middleware does not signal the App instance or the route to call the next middleware. It is the middleware that calls the next middleware and if the call $next($request, $response) is left out, then the next middleware is simply not called. The next middleware should be called, but the call can be left out conditionally to implement an authentication middleware.

Something like:

$app->add(function ($request, $response, $next) {
    $authorized = /* */;

    if ($authorized) {
        // authorized, call next middleware
        return $next($request, $response);
    }

    // not authorized, don't call next middleware and return our own response
    $body = new Body(fopen('php://temp', 'r+'));
    $body->write('Forbidden');

    return $response
        ->withBody($body)
        ->withStatus(403);
});

An example can be found in the Authorization class of the Chadicus Slim OAuth2 middleware.