Passed
Push — master ( 5f2302...77d6d7 )
by Ion
02:04
created

Jwt::validateToken()   A

Complexity

Conditions 6
Paths 4

Size

Total Lines 23
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 6
eloc 11
c 1
b 0
f 0
nc 4
nop 1
dl 0
loc 23
rs 9.2222
1
<?php
2
3
namespace IonGhitun\JwtToken;
4
5
use Carbon\Carbon;
6
use IonGhitun\JwtToken\Exceptions\JwtException;
7
8
/**
9
 * Class Jwt
10
 *
11
 * @package IonGhitun\JwtToken
12
 */
13
class Jwt
14
{
15
    /**
16
     * Generate a new JWT token.
17
     *
18
     * @param array $payload
19
     *
20
     * @return string
21
     */
22
    public static function generateToken(array $payload)
23
    {
24
        $header = self::base64EncodeUrlSafe(json_encode(['typ' => 'JWT', 'alg' => 'HS256']));
25
26
        if (!isset($payload['expiration'])) {
27
            $payload['expiration'] = Carbon::now()->addDay()->format('Y-m-d H:i:s');
28
        }
29
30
        $payload = self::base64EncodeUrlSafe(json_encode($payload));
31
        $signature = self::generateSignature($header, $payload);
32
33
        return $header . "." . $payload . "." . $signature;
34
    }
35
36
    /**
37
     * Url safe base 64 encode.
38
     *
39
     * @param string $string
40
     *
41
     * @return string|string[]
42
     */
43
    private static function base64EncodeUrlSafe(string $string)
44
    {
45
        return str_replace('=', '', strtr(base64_encode($string), '+/', '-_'));
46
    }
47
48
    /**
49
     * Generate signature
50
     *
51
     * @param $header
52
     * @param $payload
53
     * @param bool $encode
54
     *
55
     * @return string|string[]
56
     */
57
    private static function generateSignature($header, $payload, $encode = true)
58
    {
59
        $signature = hash_hmac('sha256', $header . '.' . $payload, getenv('JWT_SECRET'), true);
60
61
        if ($encode) {
62
            return self::base64EncodeUrlSafe($signature);
63
        }
64
65
        return $signature;
66
    }
67
68
    /**
69
     * Validate JWT token and return payload
70
     *
71
     * @param $token
72
     * @return mixed
73
     *
74
     * @throws JwtException
75
     */
76
    public static function validateToken($token)
77
    {
78
        $tokenData = explode('.', $token);
79
80
        if (count($tokenData) !== 3) {
81
            throw new JwtException('Not a valid JWT token!');
82
        }
83
84
        list($header64, $payload64, $signature64) = $tokenData;
85
86
        $payload = json_decode(self::base64DecodeUrlSafe($payload64), true);
87
88
        if (!$payload || !isset($payload['expiration']) || Carbon::parse($payload['expiration']) < Carbon::now()) {
89
            throw new JwtException('Jwt token expired!');
90
        }
91
92
        $signature = self::base64DecodeUrlSafe($signature64);
93
94
        if ($signature !== self::generateSignature($header64, $payload64, false)) {
95
            throw new JwtException('Could not verify Jwt token signature!');
96
        }
97
98
        return $payload;
99
    }
100
101
    /**
102
     * Url safe base 64 decode.
103
     *
104
     * @param $string
105
     *
106
     * @return false|string
107
     */
108
    private static function base64DecodeUrlSafe($string)
109
    {
110
        $mod = strlen($string) % 4;
111
112
        if ($mod !== 0) {
113
            $padlen = 4 - $mod;
114
            $string .= str_repeat('=', $padlen);
115
        }
116
117
        return base64_decode(strtr($string, '-_', '+/'));
118
    }
119
}
120