Completed
Push — master ( 580f1a...33f9ba )
by Marcel
03:23
created

Verifier::delayed()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

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