Passed
Push — master ( b5ac42...6dbb24 )
by Marco
36s
created

Parser::convertDate()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 8
ccs 4
cts 4
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 4
nc 2
nop 1
crap 2
1
<?php
2
/**
3
 * This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
4
 *
5
 * @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
6
 */
7
8
declare(strict_types=1);
9
10
namespace Lcobucci\JWT\Token;
11
12
use DateTimeImmutable;
13
use InvalidArgumentException;
14
use Lcobucci\Jose\Parsing;
15
use Lcobucci\JWT\Parser as ParserInterface;
16
use Lcobucci\JWT\Token as TokenInterface;
17
18
/**
19
 * This class parses the JWT strings and convert them into tokens
20
 *
21
 * @author Luís Otávio Cobucci Oblonczyk <[email protected]>
22
 * @since 0.1.0
23
 */
24
final class Parser implements ParserInterface
25
{
26
    /**
27
     * The data decoder
28
     *
29
     * @var Parsing\Decoder
30
     */
31
    private $decoder;
32
33
    /**
34
     * Initializes the object
35
     */
36 1
    public function __construct(Parsing\Decoder $decoder)
37
    {
38 1
        $this->decoder = $decoder;
39 1
    }
40
41
    /**
42
     * {@inheritdoc}
43
     */
44 9
    public function parse(string $jwt): TokenInterface
45
    {
46 9
        list($encodedHeaders, $encodedClaims, $encodedSignature) = $this->splitJwt($jwt);
47
48 8
        $header = $this->parseHeader($encodedHeaders);
49
50 6
        return new Plain(
51 6
            new DataSet($header, $encodedHeaders),
52 6
            new DataSet($this->parseClaims($encodedClaims), $encodedClaims),
53 6
            $this->parseSignature($header, $encodedSignature)
54
        );
55
    }
56
57
    /**
58
     * Splits the JWT string into an array
59
     *
60
     * @throws InvalidArgumentException When JWT doesn't have all parts
61
     */
62 9
    private function splitJwt(string $jwt): array
63
    {
64 9
        $data = explode('.', $jwt);
65
66 9
        if (count($data) !== 3) {
67 1
            throw new InvalidArgumentException('The JWT string must have two dots');
68
        }
69
70 8
        return $data;
71
    }
72
73
    /**
74
     * Parses the header from a string
75
     *
76
     * @throws InvalidArgumentException When an invalid header is informed
77
     */
78 8
    private function parseHeader(string $data): array
79
    {
80 8
        $header = (array) $this->decoder->jsonDecode($this->decoder->base64UrlDecode($data));
81
82 7
        if (isset($header['enc'])) {
83 1
            throw new InvalidArgumentException('Encryption is not supported yet');
84
        }
85
86 6
        return $header;
87
    }
88
89
    /**
90
     * Parses the claim set from a string
91
     */
92 6
    private function parseClaims(string $data): array
93
    {
94 6
        $claims = (array) $this->decoder->jsonDecode($this->decoder->base64UrlDecode($data));
95
96 6
        if (isset($claims[RegisteredClaims::AUDIENCE])) {
97 5
            $claims[RegisteredClaims::AUDIENCE] = (array) $claims[RegisteredClaims::AUDIENCE];
98
        }
99
100 6
        foreach (array_intersect(RegisteredClaims::DATE_CLAIMS, array_keys($claims)) as $claim) {
101 1
            $claims[$claim] = $this->convertDate((string) $claims[$claim]);
102
        }
103
104 6
        return $claims;
105
    }
106
107 1
    private function convertDate(string $value): DateTimeImmutable
108
    {
109 1
        if (strpos($value, '.') === false) {
110 1
            return new DateTimeImmutable('@' . $value);
111
        }
112
113 1
        return DateTimeImmutable::createFromFormat('U.u', $value);
114
    }
115
116
    /**
117
     * Returns the signature from given data
118
     */
119 6
    private function parseSignature(array $header, string $data): Signature
120
    {
121 6
        if ($data === '' || !isset($header['alg']) || $header['alg'] === 'none') {
122 5
            return Signature::fromEmptyData();
123
        }
124
125 1
        $hash = $this->decoder->base64UrlDecode($data);
126
127 1
        return new Signature($hash, $data);
128
    }
129
}
130