Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 22
0.00% covered (danger)
0.00%
0 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
HttpBasicAuth
0.00% covered (danger)
0.00%
0 / 22
0.00% covered (danger)
0.00%
0 / 3
132
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
20
 useAppConfig
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
20
 __invoke
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
12
1<?php
2
3/**
4 * HTTP Basic Authentication
5 *
6 * inspired by https://github.com/codeguy/Slim-Extras/blob/master/Middleware/HttpBasicAuth.php
7 *
8 * Usage:
9 *   \App::httpBasicAuth['username'] = password_hash('password', PASSWORD_DEFAULT);
10 *   // better pre-calculate hash in the config with `php -r "echo password_hash('password', PASSWORD_DEFAULT);"`
11 *   \App::$slim->add(new \BO\Slim\Middleware\HttpBasicAuth(\BO\Slim\Middleware\HttpBasicAuth::useAppConfig());
12 */
13
14namespace BO\Slim\Middleware;
15
16use Psr\Http\Message\ServerRequestInterface;
17use Psr\Http\Message\ResponseInterface;
18use Psr\Http\Server\RequestHandlerInterface;
19use BO\Slim\Factory\ResponseFactory;
20
21class HttpBasicAuth
22{
23    /**
24     * @var string
25     */
26    protected $realm;
27
28    /**
29     * @var Callable
30     */
31    protected $isAuthorized;
32
33    public function __construct(callable $isAuthorized, ?string $realm = null)
34    {
35        $this->isAuthorized = $isAuthorized;
36        $this->realm = ($realm !== null && $realm !== '' && $realm !== '0')
37            ? $realm
38            : "Password " . \App::IDENTIFIER;
39    }
40
41    public static function useAppConfig(): callable
42    {
43        return function (string $authUser, string $authPass) {
44            if (!count(\App::$httpBasicAuth)) {
45                return true;
46            }
47            if (isset(\App::$httpBasicAuth[$authUser]) && password_verify($authPass, \App::$httpBasicAuth[$authUser])) {
48                return true;
49            }
50            return false;
51        };
52    }
53
54    public function __invoke(ServerRequestInterface $request, RequestHandlerInterface $next): ResponseInterface
55    {
56        $serverParams = $request->getServerParams();
57        $authUser = $serverParams['PHP_AUTH_USER'] ?? '';
58        $authPass = $serverParams['PHP_AUTH_PW'] ?? '';
59
60        if ($this->isAuthorized instanceof \Closure) {
61            $authorized = $this->isAuthorized->call($this, $authUser, $authPass);
62        } else {
63            $authorized = ($this->isAuthorized)($authUser, $authPass);
64        }
65        if ($authorized) {
66            $response = $next->handle($request);
67        } else {
68            $response = (new ResponseFactory())->createResponse(401, 'Unauthorized');
69            $response = $response->withHeader('WWW-Authenticate', sprintf('Basic realm="%s"', $this->realm));
70        }
71
72        return $response;
73    }
74}