Completed
Push — master ( b98068...3382d8 )
by Sébastien
03:40
created

JwtAuthMiddleware::process()   B

Complexity

Conditions 8
Paths 17

Size

Total Lines 57
Code Lines 33

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 29
CRAP Score 8

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 57
ccs 29
cts 29
cp 1
rs 7.2648
cc 8
eloc 33
nc 17
nop 2
crap 8

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Soluble\Wallit\Middleware;
6
7
use Interop\Http\ServerMiddleware\DelegateInterface;
8
use Interop\Http\ServerMiddleware\MiddlewareInterface as ServerMiddlewareInterface;
9
use Psr\Http\Message\ServerRequestInterface;
10
use Soluble\Wallit\Service\JwtService;
11
use Soluble\Wallit\Token\Provider\ServerRequestLazyChainProvider;
12
use Zend\Diactoros\Response\JsonResponse;
13
use Zend\Diactoros\Response\RedirectResponse;
14
use Psr\Http\Message\ResponseInterface;
15
16
class JwtAuthMiddleware implements ServerMiddlewareInterface
17
{
18
    public const DEFAULT_OPTIONS = [
19
        self::OPTION_ALLOW_INSECURE_HTTP => false,
20
        self::OPTION_RELAXED_HOSTS       => [],
21
    ];
22
23
    public const OPTION_ALLOW_INSECURE_HTTP = 'allow_insecure_http';
24
    public const OPTION_RELAXED_HOSTS = 'relaxed_hosts';
25
26
    /**
27
     * @var array
28
     */
29
    protected $tokenProviders = [];
30
31
    /**
32
     * @var JwtService
33
     */
34
    protected $jwtService;
35
36
    /**
37
     * @var array
38
     */
39
    protected $options;
40
41
    /**
42
     * JwtAuthMiddleware constructor.
43
     *
44
     * @param array      $tokenProviders lazy loaded token providers
45
     * @param JwtService $jwtService
46
     */
47 9
    public function __construct(array $tokenProviders,
48
                                JwtService $jwtService,
49
                                array $options = [])
50
    {
51 9
        $this->tokenProviders = $tokenProviders;
52 9
        $this->jwtService = $jwtService;
53 9
        $this->options = array_merge(self::DEFAULT_OPTIONS, $options);
54 9
    }
55
56
    /**
57
     * @throws Exception\InsecureSchemeException
58
     *
59
     * @param ServerRequestInterface $request
60
     * @param DelegateInterface      $delegate
61
     *
62
     * @return ResponseInterface|RedirectResponse
63
     */
64 8
    public function process(ServerRequestInterface $request, DelegateInterface $delegate): ResponseInterface
65
    {
66
        // 1. Check for secure scheme (with exception of relaxed_hosts)
67
68 8
        $scheme = strtolower($request->getUri()->getScheme());
69 8
        if ($this->options['allow_insecure_http'] !== true && $scheme !== 'https') {
70 2
            $host = $request->getUri()->getHost();
71 2
            $relaxed_hosts = (array) $this->options['relaxed_hosts'];
72 2
            if (!in_array($host, $relaxed_hosts, true)) {
73 1
                throw new Exception\InsecureSchemeException(sprintf(
74 1
                    'Insecure scheme (%s) denied by configuration.',
75 1
                    $scheme
76
                ));
77
            }
78
        }
79
80
        // 2. Fetch token from server request
81
82 7
        $tokenProvider = new ServerRequestLazyChainProvider($request, $this->tokenProviders);
83
84 7
        $plainToken = $tokenProvider->getPlainToken();
85
86
        // 3. Validate the token
87 7
        if ($plainToken !== null) {
88
            try {
89 6
                $token = $this->jwtService->parsePlainToken($plainToken);
90
91 5
                if ($token->verify($this->jwtService->getSigner(), $this->jwtService->getPrivateKey())) {
92 4
                    if ($token->isExpired()) {
93 1
                        $message = 'Token has expired';
94
                    } else {
95 3
                        $authenticated = true;
0 ignored issues
show
Unused Code introduced by
$authenticated is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
96
                        // log Something ?
97 3
                        $response = $delegate->process($request->withAttribute(self::class, $token));
98
                        // do something with the response (writing cookie, refresh token ?)
99 3
                        return $response;
100
                    }
101
                } else {
102 1
                    $message = 'Token is invalid';
103
                }
104 1
            } catch (\Throwable $e) {
105
                // log something ?
106 1
                $message = 'Token error';
107
            }
108
        } else {
109 1
            $message = 'No token provided';
110
        }
111
112
        // @todo: ask the correct way with PSR-15 ?
113 4
        $error = new JsonResponse([
114 4
            'message' => 'Unauthorized.',
115 4
            'reason'  => $message,
116 4
            'code'    => 401
117 4
        ], 401, []);
118
119 4
        return $error;
120
    }
121
}
122