RequestSignatureMiddleware::__invoke()   C
last analyzed

Complexity

Conditions 7
Paths 8

Size

Total Lines 35
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 35
rs 6.7272
c 0
b 0
f 0
cc 7
eloc 22
nc 8
nop 2
1
<?php declare(strict_types = 1);
2
3
namespace Link0\Bunq\Middleware;
4
5
use GuzzleHttp\Psr7\Request;
6
use Link0\Bunq\Domain\Keypair\PrivateKey;
7
use Psr\Http\Message\RequestInterface;
8
9
final class RequestSignatureMiddleware
10
{
11
    const SIGNATURE_ALGORITHM = OPENSSL_ALGO_SHA256;
12
13
    /**
14
     * @var PrivateKey
15
     */
16
    private $privateKey;
17
18
    /**
19
     * @param PrivateKey $privateKey
20
     */
21
    public function __construct(PrivateKey $privateKey)
22
    {
23
        $this->privateKey = $privateKey;
24
    }
25
26
    /**
27
     * @param string $data
28
     * @return string
29
     * @throws \Exception
30
     */
31
    public function sign(string $data): string
32
    {
33
        if (openssl_sign($data, $signature, $this->privateKey, static::SIGNATURE_ALGORITHM) !== true) {
34
            throw new \Exception("Could not sign request: " . openssl_error_string());
35
        }
36
        return $signature;
37
    }
38
    /**
39
     * @param RequestInterface $request
40
     * @param array            $options
41
     *
42
     * @return Request
43
     */
44
    public function __invoke(RequestInterface $request, array $options = [])
45
    {
46
        $headers = $request->getHeaders();
47
        ksort($headers);
48
49
        $signatureData = $request->getMethod() . ' ' . $request->getRequestTarget();
50
        foreach ($headers as $header => $values) {
51
            foreach ($values as $value) {
52
                if ($header === 'User-Agent'
53
                    || $header === 'Cache-Control'
54
                    || substr($header, 0, 7) === 'X-Bunq-') {
55
                    $signatureData .= PHP_EOL . $header . ': ' . $value;
56
                }
57
            }
58
        }
59
        $signatureData .= "\n\n";
60
61
        $body = (string) $request->getBody();
62
        if (!empty($body)) {
63
            $signatureData .= $body;
64
        }
65
66
        $signature = $this->sign($signatureData);
67
68
        $headers['X-Bunq-Client-Signature'] = base64_encode($signature);
69
70
        $signedRequest = new Request(
71
            $request->getMethod(),
72
            $request->getUri(),
73
            $headers,
74
            $request->getBody()
75
        );
76
77
        return $signedRequest;
78
    }
79
}
80