WebhookAuthenticator::authenticateClientIp()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 10
ccs 0
cts 10
cp 0
rs 9.9332
c 0
b 0
f 0
cc 2
nc 2
nop 1
crap 6
1
<?php
2
3
namespace Xsolla\SDK\Webhook;
4
5
use Symfony\Component\HttpFoundation\IpUtils;
6
use Xsolla\SDK\Exception\Webhook\InvalidClientIpException;
7
use Xsolla\SDK\Exception\Webhook\InvalidSignatureException;
8
9
class WebhookAuthenticator
10
{
11
    protected static $xsollaSubnets = [
12
        '159.255.220.240/28',
13
        '185.30.20.16/29',
14
        '185.30.21.0/24',
15
        '185.30.21.16/29',
16
    ];
17
18
    /**
19
     * @var string
20
     */
21
    protected $projectSecretKey;
22
23
    /**
24
     * @param string $projectSecretKey
25
     */
26
    public function __construct($projectSecretKey)
27
    {
28
        $this->projectSecretKey = $projectSecretKey;
29
    }
30
31
    /**
32
     * @param WebhookRequest $webhookRequest
33
     * @param bool           $checkClientIp
34
     *
35
     * @throws InvalidClientIpException
36
     * @throws InvalidSignatureException
37
     */
38
    public function authenticate(WebhookRequest $webhookRequest, $checkClientIp = true)
39
    {
40
        if (true === $checkClientIp) {
41
            $this->authenticateClientIp($webhookRequest->getClientIp());
42
        }
43
        $this->authenticateSignature($webhookRequest);
44
    }
45
46
    /**
47
     * @param string $clientIp
48
     *
49
     * @throws InvalidClientIpException
50
     */
51
    public function authenticateClientIp($clientIp)
52
    {
53
        if (false === IpUtils::checkIp($clientIp, self::$xsollaSubnets)) {
54
            throw new InvalidClientIpException(sprintf(
55
                'Client IP address (%s) not found in allowed IP addresses whitelist (%s). Please check troubleshooting section in README.md https://github.com/xsolla/xsolla-sdk-php#troubleshooting',
56
                $clientIp,
57
                implode(', ', self::$xsollaSubnets)
58
            ));
59
        }
60
    }
61
62
    /**
63
     * @param WebhookRequest $webhookRequest
64
     *
65
     * @throws InvalidSignatureException
66
     */
67
    public function authenticateSignature(WebhookRequest $webhookRequest)
68
    {
69
        $headers = $webhookRequest->getHeaders();
70
        if (!array_key_exists('authorization', $headers)) {
71
            throw new InvalidSignatureException('"Authorization" header not found in Xsolla webhook request. Please check troubleshooting section in README.md https://github.com/xsolla/xsolla-sdk-php#troubleshooting');
72
        }
73
        $matches = [];
74
        preg_match('~^Signature ([0-9a-f]{40})$~', $headers['authorization'], $matches);
75
        if (array_key_exists(1, $matches)) {
76
            $clientSignature = $matches[1];
77
        } else {
78
            throw new InvalidSignatureException('Signature not found in "Authorization" header from Xsolla webhook request: '.$headers['authorization']);
79
        }
80
        $serverSignature = sha1($webhookRequest->getBody().$this->projectSecretKey);
81
        if ($clientSignature !== $serverSignature) {
82
            throw new InvalidSignatureException("Invalid Signature. Signature provided in \"Authorization\" header ($clientSignature) does not match with expected");
83
        }
84
    }
85
}
86