Passed
Pull Request — master (#5)
by Joao
06:22
created

JwtWrapper   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 139
Duplicated Lines 0 %

Test Coverage

Coverage 82.98%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 14
eloc 41
c 2
b 0
f 0
dl 0
loc 139
ccs 39
cts 47
cp 0.8298
rs 10

8 Methods

Rating   Name   Duplication   Size   Complexity  
A getAuthorizationBearer() 0 10 3
A generateSecret() 0 3 1
A __construct() 0 7 2
A generateToken() 0 15 1
A getLeeway() 0 3 1
A setLeeway() 0 3 1
A createJwtData() 0 18 1
A extractData() 0 19 4
1
<?php
2
3
namespace ByJG\Util;
4
5
use Firebase\JWT\JWT;
6
7
class JwtWrapper
8
{
9
10
    protected $serverName;
11
12
    /**
13
     * @var JwtKeyInterface
14
     */
15
    protected $jwtKey;
16
17
    /**
18
     * JwtWrapper constructor.
19
     * @param string $serverName
20
     * @param JwtKeyInterface $jwtKey
21
     * @throws JwtWrapperException
22
     */
23 18
    public function __construct($serverName, $jwtKey)
24
    {
25 18
        $this->serverName = $serverName;
26 18
        $this->jwtKey = $jwtKey;
27
28 18
        if (!($jwtKey instanceof JwtKeyInterface)) {
0 ignored issues
show
introduced by
$jwtKey is always a sub-type of ByJG\Util\JwtKeyInterface.
Loading history...
29
            throw new JwtWrapperException('Constructor needs to receive a JwtKeyInterface');
30
        }
31 18
    }
32
33
    /**
34
     * @param $data
35
     * @param int $secondsExpire In Seconds
36
     * @param int $secondsNotBefore In Seconds
37
     * @return array
38
     */
39 12
    public function createJwtData($data, $secondsExpire = 60, $secondsNotBefore = 0)
40
    {
41 12
        $tokenId    = base64_encode(openssl_random_pseudo_bytes(32));
42 12
        $issuedAt   = time();
43 12
        $notBefore  = $issuedAt + $secondsNotBefore;          //Adding 10 seconds
44 12
        $expire     = $notBefore + $secondsExpire;            // Adding 60 seconds
45 12
        $serverName = $this->serverName;                       // Retrieve the server name from config file
46
47
        /*
48
         * Create the token as an array
49
         */
50
        return [
51 12
            'iat'  => $issuedAt,         // Issued at: time when the token was generated
52 12
            'jti'  => $tokenId,          // Json Token Id: an unique identifier for the token
53 12
            'iss'  => $serverName,       // Issuer
54 12
            'nbf'  => $notBefore,        // Not before
55 12
            'exp'  => $expire,           // Expire
56 12
            'data' => $data              // Data related to the signer user
57
        ];
58
    }
59
60 12
    public function generateToken($jwtData)
61
    {
62
        /*
63
         * Encode the array to a JWT string.
64
         * Second parameter is the key to encode the token.
65
         *
66
         * The output string can be validated at http://jwt.io/
67
         */
68 12
        $jwt = JWT::encode(
69 12
            $jwtData,      //Data to be encoded in the JWT
70 12
            $this->jwtKey->getPrivateKey(), // The signing key
71 12
            $this->jwtKey->getAlghoritm()
72
        );
73
74 12
        return $jwt;
75
    }
76
77
    /**
78
     * Extract the key, which is coming from the config file.
79
     *
80
     * Best suggestion is the key to be a binary string and
81
     * store it in encoded in a config file.
82
     *
83
     * Can be generated with base64_encode(openssl_random_pseudo_bytes(64));
84
     *
85
     * keep it secure! You'll need the exact key to verify the
86
     * token later.
87
     *
88
     * @param null $bearer
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $bearer is correct as it would always require null to be passed?
Loading history...
89
     * @return object
90
     * @throws JwtWrapperException
91
     */
92 18
    public function extractData($bearer = null)
93
    {
94 18
        if (empty($bearer)) {
95 4
            $bearer = $this->getAuthorizationBearer();
96
        }
97
98 16
        $jwtData = JWT::decode(
99 16
            $bearer,
100 16
            $this->jwtKey->getPublicKey(),
101
            [
102 16
                $this->jwtKey->getAlghoritm()
103
            ]
104
        );
105
106 6
        if (isset($jwtData->iss) && $jwtData->iss != $this->serverName) {
107 2
            throw new JwtWrapperException("Issuer does not match");
108
        }
109
110 4
        return $jwtData;
111
    }
112
113
    /**
114
     * @return mixed
115
     * @throws JwtWrapperException
116
     */
117 4
    public function getAuthorizationBearer()
118
    {
119 4
        $authorization = isset($_SERVER['HTTP_AUTHORIZATION']) ? $_SERVER['HTTP_AUTHORIZATION'] : "";
120 4
        list($bearer) = sscanf($authorization, 'Bearer %s');
121
122 4
        if (empty($bearer)) {
123 2
            throw new JwtWrapperException('Absent authorization token');
124
        }
125
126 2
        return $bearer;
127
    }
128
129
    public static function generateSecret($bytes)
130
    {
131
        return base64_encode(openssl_random_pseudo_bytes($bytes));
132
    }
133
    
134
    /**
135
     * @param int $seconds A value no more than few minutes (in seconds) e.g. 60
136
     * @see: https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.4
137
     */
138
    public function setLeeway($seconds)
139
    {
140
        JWT::$leeway = $seconds;
141
    }
142
    
143
    public function getLeeway()
144
    {
145
        return JWT::$leeway;
146
    }
147
}
148