Completed
Push — master ( 02cfb9...95b30c )
by Artem
06:06
created

JwtGenerator   A

Complexity

Total Complexity 7

Size/Duplication

Total Lines 98
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 0
Metric Value
wmc 7
lcom 1
cbo 2
dl 0
loc 98
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A generateToken() 0 14 1
A buildHeaderPart() 0 9 1
A buildPayloadPart() 0 4 1
A buildSignaturePart() 0 7 1
A convertArrayToJsonString() 0 4 1
A base64EncodeUrlSafe() 0 4 1
1
<?php
2
/*
3
 * This file is part of the FreshCentrifugoBundle.
4
 *
5
 * (c) Artem Henvald <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
declare(strict_types=1);
12
13
namespace Fresh\CentrifugoBundle\Service\Jwt;
14
15
use Fresh\CentrifugoBundle\Token\JwtAlgorithm;
16
use Fresh\CentrifugoBundle\Token\JwtPayloadInterface;
17
18
/**
19
 * JwtGenerator.
20
 *
21
 * @author Artem Henvald <[email protected]>
22
 */
23
class JwtGenerator
24
{
25
    private const HMAC_ALGORITHM = 'sha256';
26
27
    /** @var string */
28
    private $secret;
29
30
    /** @var string */
31
    private $centrifugoJwtAlgorithm;
32
33
    /**
34
     * @param string $centrifugoSecret
35
     * @param string $centrifugoJwtAlgorithm
36
     */
37
    public function __construct(string $centrifugoSecret, string $centrifugoJwtAlgorithm)
38
    {
39
        $this->secret = $centrifugoSecret;
40
        JwtAlgorithm::assertValidAlgorithm($centrifugoJwtAlgorithm);
41
        $this->centrifugoJwtAlgorithm = $centrifugoJwtAlgorithm;
42
    }
43
44
    /**
45
     * @param JwtPayloadInterface $payload
46
     *
47
     * @return string
48
     */
49
    public function generateToken(JwtPayloadInterface $payload): string
50
    {
51
        $headerPart = $this->buildHeaderPart();
52
        $payloadPart = $this->buildPayloadPart($payload);
53
54
        $headerPartEncoded = $this->base64EncodeUrlSafe($headerPart);
55
        $payloadPartEncoded = $this->base64EncodeUrlSafe($payloadPart);
56
57
        return \implode('.', [
58
            $headerPartEncoded,
59
            $payloadPartEncoded,
60
            $this->buildSignaturePart($headerPartEncoded, $payloadPartEncoded),
61
        ]);
62
    }
63
64
    /**
65
     * @return string
66
     */
67
    private function buildHeaderPart(): string
68
    {
69
        $header = [
70
            'typ' => 'JWT',
71
            'alg' => $this->centrifugoJwtAlgorithm,
72
        ];
73
74
        return $this->convertArrayToJsonString($header);
75
    }
76
77
    /**
78
     * @param JwtPayloadInterface $payload
79
     *
80
     * @return string
81
     */
82
    private function buildPayloadPart(JwtPayloadInterface $payload): string
83
    {
84
        return $this->convertArrayToJsonString($payload->getPayloadData());
85
    }
86
87
    /**
88
     * @param string $headerPartDecoded
89
     * @param string $payloadPartDecoded
90
     *
91
     * @return string
92
     */
93
    private function buildSignaturePart(string $headerPartDecoded, string $payloadPartDecoded): string
94
    {
95
        $data = $headerPartDecoded.'.'.$payloadPartDecoded;
96
        $hash = \hash_hmac(self::HMAC_ALGORITHM, $data, $this->secret, true);
97
98
        return $this->base64EncodeUrlSafe($hash);
99
    }
100
101
    /**
102
     * @param array $array
103
     *
104
     * @return string
105
     */
106
    private function convertArrayToJsonString(array $array): string
107
    {
108
        return \json_encode($array, \JSON_THROW_ON_ERROR);
109
    }
110
111
    /**
112
     * @param string $string
113
     *
114
     * @return string
115
     */
116
    private function base64EncodeUrlSafe(string $string): string
117
    {
118
        return \str_replace(['+', '/', '='], ['-', '_', ''], \base64_encode($string));
119
    }
120
}
121