Completed
Pull Request — master (#869)
by
unknown
01:50
created

Introspector::verifyToken()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 9
ccs 6
cts 6
cp 1
rs 9.6666
cc 2
eloc 5
nc 2
nop 1
crap 2
1
<?php
2
3
namespace League\OAuth2\Server;
4
5
use Exception;
6
use Lcobucci\JWT\Signer\Keychain;
7
use Lcobucci\JWT\Signer\Rsa\Sha256;
8
use Lcobucci\JWT\Token;
9
use Lcobucci\JWT\ValidationData;
10
use League\OAuth2\Server\CryptKey;
11
use League\OAuth2\Server\Exception\OAuthServerException;
12
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
13
use Psr\Http\Message\ResponseInterface;
14
use Psr\Http\Message\ServerRequestInterface;
15
use Lcobucci\JWT\Parser;
16
use League\OAuth2\Server\ResponseTypes\IntrospectionResponse;
17
18
class Introspector
19
{
20
    /**
21
     * @var AccessTokenRepositoryInterface
22
     */
23
    private $accessTokenRepository;
24
25
    /**
26
     * @var CryptKey
27
     */
28
    private $privateKey;
29
30
    /**
31
     * @var Parser
32
     */
33
    private $parser;
34
35
    /**
36
     * New Introspector instance.
37
     *
38
     * @param AccessTokenRepositoryInterface $accessTokenRepository
39
     * @param CryptKey                       $privateKey
40
     * @param Parser                         $parser
41
     */
42 5
    public function __construct(
43
        AccessTokenRepositoryInterface $accessTokenRepository,
44
        CryptKey $privateKey,
45
        Parser $parser
46
    )
47
    {
48 5
        $this->accessTokenRepository = $accessTokenRepository;
49 5
        $this->privateKey = $privateKey;
50 5
        $this->parser = $parser;
51 5
    }
52
53
    /**
54
     * Return an introspection response.
55
     *
56
     * @param ServerRequestInterface $request
57
     *
58
     * @return IntrospectionResponse
59
     */
60 5
    public function respondToIntrospectionRequest(ServerRequestInterface $request)
61
    {
62 5
        $jwt = $request->getParsedBody()['token'] ?? null;
63
64
        try {
65 5
            $token = $this->parser->parse($jwt);
66
67 4
            $this->verifyToken($token);
68 3
            $this->checkIfTokenIsExpired($token);
69 2
            $this->checkIfTokenIsRevoked($token);
70
71 1
            return $this->createActiveResponse($token);
72
        }
73 4
        catch(Exception $ex) {
74 4
            return $this->createInactiveResponse();
75
        }
76
    }
77
78
    /**
79
     * Validate the JWT token.
80
     *
81
     * @param Token $token
82
     *
83
     * @throws OAuthServerException
84
     */
85 4
    private function verifyToken(Token $token)
86
    {
87 4
        $keychain = new Keychain();
88 4
        $key = $keychain->getPrivateKey($this->privateKey->getKeyPath(), $this->privateKey->getPassPhrase());
89
90 4
        if (!$token->verify(new Sha256, $key)) {
91 1
            throw OAuthServerException::accessDenied('Access token could not be verified');
92
        }
93 3
    }
94
95
    /**
96
     * Ensure access token hasn't expired
97
     *
98
     * @param Token $token
99
     *
100
     * @throws OAuthServerException
101
     */
102 3
    private function checkIfTokenIsExpired(Token $token)
103
    {
104 3
        $data = new ValidationData(time());
105
106 3
        if (!$token->validate($data)) {
107 1
            throw OAuthServerException::accessDenied('Access token is invalid');
108
        }
109 2
    }
110
111
    /**
112
     * Check if the given access token is revoked.
113
     *
114
     * @param Token $token
115
     *
116
     * @throws OAuthServerException
117
     */
118 2
    private function checkIfTokenIsRevoked(Token $token)
119
    {
120 2
        if ($this->accessTokenRepository->isAccessTokenRevoked($token->getClaim('jti'))) {
121 1
            throw OAuthServerException::accessDenied('Access token has been revoked');
122
        }
123 1
    }
124
125
    /**
126
     * Create active introspection response.
127
     *
128
     * @param Token             $token
129
     *
130
     * @return IntrospectionResponse
131
     */
132 1
    private function createActiveResponse(Token $token)
133
    {
134 1
        $response = new IntrospectionResponse();
135
136 1
        $response->setIntrospectionData(
137
            [
138 1
                'active' => true,
139 1
                'token_type' => 'access_token',
140 1
                'scope' => $token->getClaim('scopes', ''),
141 1
                'client_id' => $token->getClaim('aud'),
142 1
                'exp' => $token->getClaim('exp'),
143 1
                'iat' => $token->getClaim('iat'),
144 1
                'sub' => $token->getClaim('sub'),
145 1
                'jti' => $token->getClaim('jti'),
146
            ]
147
            );
148
149 1
        return $response;
150
    }
151
152
    /**
153
     * Create inactive introspection response
154
     *
155
     * @return IntrospectionResponse
156
     */
157 4
    private function createInactiveResponse()
158
    {
159 4
        $response = new IntrospectionResponse();
160
161 4
        $response->setIntrospectionData(
162
            [
163 4
                'active' => false,
164
            ]
165
        );
166
167 4
        return $response;
168
    }
169
}
170