Completed
Push — master ( 376ce6...0eb5fa )
by Marcel
02:57
created

Signer::withDateHeader()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 1
crap 1
1
<?php
2
3
namespace UMA\Psr\Http\Message\HMAC;
4
5
use Psr\Http\Message\MessageInterface;
6
use Psr\Http\Message\RequestInterface;
7
use UMA\Psr\Http\Message\Internal\HashCalculator;
8
use UMA\Psr\Http\Message\Internal\TimeProvider;
9
use UMA\Psr\Http\Message\Serializer\MessageSerializer;
10
11
class Signer
12
{
13
    /**
14
     * @var string
15
     */
16
    private $secret;
17
18
    /**
19
     * @var HashCalculator
20
     */
21
    private $calculator;
22
23
    /**
24
     * @var TimeProvider
25
     */
26
    private $timeProvider;
27
28
    /**
29
     * @param string $secret
30
     */
31 91
    public function __construct($secret)
32
    {
33 91
        $this->secret = $secret;
34 91
        $this->calculator = new HashCalculator();
35 91
        $this->timeProvider = new TimeProvider();
36 91
    }
37
38
    /**
39
     * @param MessageInterface $message
40
     *
41
     * @return MessageInterface The signed message.
42
     *
43
     * @throws \InvalidArgumentException When $message is an implementation of
44
     *                                   MessageInterface that cannot be
45
     *                                   serialized and thus neither signed.
46
     */
47 91
    public function sign(MessageInterface $message)
48
    {
49 91
        $serialization = MessageSerializer::serialize(
50 91
            $preSignedMessage = $this->withSignedHeadersHeader($this->withDateHeader($message))
51 91
        );
52
53 91
        return $preSignedMessage->withHeader(
54 91
            Specification::AUTH_HEADER,
55 91
            Specification::AUTH_PREFIX.$this->calculator->hmac($serialization, $this->secret)
56 91
        );
57
    }
58
59
    /**
60
     * @param MessageInterface $message
61
     *
62
     * @return MessageInterface
63
     */
64 91
    private function withSignedHeadersHeader(MessageInterface $message)
65
    {
66 91
        $headers = array_keys(array_change_key_case($message->getHeaders(), CASE_LOWER));
67 91
        array_push($headers, mb_strtolower(Specification::SIGN_HEADER));
68
69
        // Some of the tested RequestInterface implementations do not include
70
        // the Host header in $message->getHeaders(), so it is explicitly set when needed
71 91
        if ($message instanceof RequestInterface && !in_array('host', $headers)) {
72 18
            array_push($headers, 'host');
73 18
        }
74
75
        // There is no guarantee about the order of the headers returned by
76
        // $message->getHeaders(), so they are explicitly sorted in order
77
        // to produce the exact same string regardless of the underlying implementation
78 91
        sort($headers);
79
80 91
        return $message->withHeader(Specification::SIGN_HEADER, implode(',', $headers));
81
    }
82
83
    /**
84
     * @param MessageInterface $message
85
     *
86
     * @return MessageInterface
87
     */
88 91
    private function withDateHeader(MessageInterface $message)
89
    {
90 91
        return $message->withHeader(Specification::DATE_HEADER, $this->timeProvider->currentTime());
91
    }
92
}
93