Completed
Push — master ( 5b2039...ff2518 )
by Marcel
06:16
created

Verifier::__construct()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 10
ccs 9
cts 9
cp 1
rs 9.4285
cc 2
eloc 8
nc 2
nop 1
crap 2
1
<?php
2
3
namespace UMA\Psr7Hmac;
4
5
use Psr\Http\Message\MessageInterface;
6
use UMA\Psr7Hmac\Inspector\DefaultInspector;
7
use UMA\Psr7Hmac\Inspector\InspectorInterface;
8
use UMA\Psr7Hmac\Internal\HashCalculator;
9
use UMA\Psr7Hmac\Internal\HeaderValidator;
10
use UMA\Psr7Hmac\Internal\MessageSerializer;
11
12
class Verifier
13
{
14
    /**
15
     * @var HashCalculator
16
     */
17
    private $calculator;
18
19
    /**
20
     * @var InspectorInterface
21
     */
22
    private $inspector;
23
24
    /**
25
     * @var HeaderValidator
26
     */
27
    private $validator;
28
29
    /**
30
     * @param InspectorInterface|null $inspector
31
     */
32 98
    public function __construct(InspectorInterface $inspector = null)
33
    {
34 98
        $this->calculator = new HashCalculator();
35 98
        $this->inspector = null === $inspector ?
36 98
            new DefaultInspector() : $inspector;
37 98
        $this->validator = (new HeaderValidator())
38 98
            ->addRule(Specification::AUTH_HEADER, Specification::AUTH_REGEXP)
39 98
            ->addRule(Specification::NONCE_HEADER, Specification::NONCE_REGEXP)
40 98
            ->addRule(Specification::SIGN_HEADER, Specification::SIGN_REGEXP);
41 98
    }
42
43
    /**
44
     * @param MessageInterface $message
45
     * @param string           $secret
46
     *
47
     * @return bool Signature verification outcome.
48
     *
49
     * @throws \InvalidArgumentException When $message is an implementation of
50
     *                                   MessageInterface that cannot be
51
     *                                   serialized and thus neither verified.
52
     */
53 98
    public function verify(MessageInterface $message, $secret)
54
    {
55 98
        if (false === $matches = $this->validator->conforms($message)) {
56 91
            return false;
57
        }
58
59 77
        $clientSideSignature = $matches[Specification::AUTH_HEADER][1];
60
61 77
        $serverSideSignature = $this->calculator
62 77
            ->hmac(MessageSerializer::serialize($this->withoutUnsignedHeaders($message)), $secret);
63
64 77
        $vetted = $this->inspector
65 77
            ->vet($message, $verified = hash_equals($serverSideSignature, $clientSideSignature));
66
67 77
        return $vetted && $verified;
68
    }
69
70
    /**
71
     * @param MessageInterface $message
72
     *
73
     * @return MessageInterface
74
     */
75 77
    private function withoutUnsignedHeaders(MessageInterface $message)
76
    {
77 77
        $signedHeaders = array_filter(explode(',', $message->getHeaderLine(Specification::SIGN_HEADER)));
78
79 77
        foreach (array_keys($message->getHeaders()) as $headerName) {
80 77
            if (!in_array(mb_strtolower($headerName), $signedHeaders)) {
81 77
                $message = $message->withoutHeader($headerName);
82 77
            }
83 77
        }
84
85 77
        return $message;
86
    }
87
}
88