Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
2 / 2
CRAP
100.00% covered (success)
100.00%
23 / 23
BasicAuthentication
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
2 / 2
12
100.00% covered (success)
100.00%
23 / 23
 __construct
100.00% covered (success)
100.00%
1 / 1
10
100.00% covered (success)
100.00%
20 / 20
 logout
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
3 / 3
1<?php
2
3namespace Miniframe\Middleware;
4
5use Miniframe\Core\AbstractMiddleware;
6use Miniframe\Core\Config;
7use Miniframe\Core\Request;
8use Miniframe\Core\Response;
9use Miniframe\Response\RedirectResponse;
10use Miniframe\Response\UnauthorizedResponse;
11
12/**
13 * Basic HTTP Authentication class
14 *
15 * This middleware adds basic HTTP authentication to your application.
16 */
17class BasicAuthentication extends AbstractMiddleware
18{
19    /**
20     * Forces the user to be logged in
21     *
22     * @param Request $request Reference to the Request object.
23     * @param Config  $config  Reference to the Config object.
24     */
25    public function __construct(Request $request, Config $config)
26    {
27        parent::__construct($request, $config);
28
29        // Don't do authentication on shell requests
30        if ($request->isShellRequest()) {
31            return;
32        }
33
34        // Check if the current path is part of the exclusion list
35        $fullPath = '/' . implode('/', $request->getPath()); // $_SERVER['REQUEST_URI'] can't be used since
36                                                                  // that doesn't apply on Console requests
37        $excludeList = $config->has('authentication', 'exclude') ? $config->get('authentication', 'exclude') : [];
38        foreach ($excludeList as $excludePath) {
39            $regex = '/^' . str_replace(['?', '\\*'], ['.', '.*?'], preg_quote($excludePath, '/')) . '$/';
40            if (preg_match($regex, $fullPath)) {
41                return;
42            }
43        }
44
45        // Fetches the realm
46        $realm = $this->config->get('authentication', 'realm');
47
48        // Check if we have credentials
49        if (!$request->getServer('PHP_AUTH_USER') || !$request->getServer('PHP_AUTH_PW')) {
50            throw new UnauthorizedResponse($realm);
51        }
52
53        // Fetch user table
54        $userTable = $config->get('authentication', 'user');
55        if (!is_array($userTable)) {
56            throw new \RuntimeException('The usertable is invalid. Please check your configuration.');
57        }
58
59        // Is the username valid?
60        if (!isset($userTable[$request->getServer('PHP_AUTH_USER')])) {
61            throw new UnauthorizedResponse($realm);
62        }
63
64        // Is the password valid?
65        if (!password_verify($request->getServer('PHP_AUTH_PW'), $userTable[$request->getServer('PHP_AUTH_USER')])) {
66            throw new UnauthorizedResponse($realm);
67        }
68
69        // We passed the BasicAuthentication middleware, continue.
70    }
71
72    /**
73     * Returns a response that forces the user to log out
74     *
75     * @return Response
76     */
77    public function logout(): Response
78    {
79        $url = $this->request->isHttpsRequest() ? 'https' : 'http';
80        $url .= '://logout@' . $this->request->getServer('HTTP_HOST') . $this->config->get('framework', 'base_href');
81        return new RedirectResponse($url);
82    }
83}