Completed
Pull Request — master (#925)
by
unknown
01:38
created

Introspector   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 138
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 13
lcom 1
cbo 4
dl 0
loc 138
ccs 31
cts 31
cp 1
rs 10
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 9 1
A respondToIntrospectionRequest() 0 16 3
A isTokenValid() 0 4 3
A verifyToken() 0 7 1
A isTokenExpired() 0 6 1
A isTokenRevoked() 0 4 1
A setTokenOnResponse() 0 6 1
A validateIntrospectionRequest() 0 6 2
1
<?php
2
3
namespace League\OAuth2\Server;
4
5
use InvalidArgumentException;
6
use Lcobucci\JWT\Parser;
7
use Lcobucci\JWT\Signer\Keychain;
8
use Lcobucci\JWT\Signer\Rsa\Sha256;
9
use Lcobucci\JWT\Token;
10
use Lcobucci\JWT\ValidationData;
11
use League\OAuth2\Server\Exception\OAuthServerException;
12
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
13
use League\OAuth2\Server\ResponseTypes\IntrospectionResponse;
14
use Psr\Http\Message\ServerRequestInterface;
15
16
class Introspector
17
{
18
    /**
19
     * @var AccessTokenRepositoryInterface
20
     */
21
    private $accessTokenRepository;
22
23
    /**
24
     * @var CryptKey
25
     */
26
    private $privateKey;
27
28
    /**
29
     * @var Parser
30
     */
31
    private $parser;
32
33
    /**
34
     * New Introspector instance.
35
     *
36
     * @param AccessTokenRepositoryInterface $accessTokenRepository
37
     * @param CryptKey                       $privateKey
38
     * @param Parser                         $parser
39
     */
40 9
    public function __construct(
41
        AccessTokenRepositoryInterface $accessTokenRepository,
42
        CryptKey $privateKey,
43
        Parser $parser
44
    ) {
45 9
        $this->accessTokenRepository = $accessTokenRepository;
46 9
        $this->privateKey = $privateKey;
47 9
        $this->parser = $parser;
48 9
    }
49
50
    /**
51
     * Validate the request
52
     *
53
     * @param ServerRequestInterface $request
54
     *
55
     * @throws OAuthServerException
56
     */
57 2
    public function validateIntrospectionRequest(ServerRequestInterface $request)
58
    {
59 2
        if ($request->getMethod() !== 'POST') {
60 1
            throw OAuthServerException::accessDenied('Invalid request method');
61
        }
62 1
    }
63
64
    /**
65
     * Return an introspection response.
66
     *
67
     * @param ServerRequestInterface $request
68
     * @param IntrospectionResponse  $responseType
69
     *
70
     * @return IntrospectionResponse
71
     */
72 7
    public function respondToIntrospectionRequest(
73
        ServerRequestInterface $request,
74
        IntrospectionResponse $responseType
75
    ) {
76 7
        $jwt = $request->getParsedBody()['token'] ?? null;
77
78
        try {
79 7
            $token = $this->parser->parse($jwt);
80 1
        } catch (InvalidArgumentException $e) {
81 1
            return $responseType;
82
        }
83
84 6
        return $this->isTokenValid($token) ?
85 3
            $this->setTokenOnResponse($token, $responseType) :
86 6
            $responseType;
87
    }
88
89
    /**
90
     * Validate the JWT and make sure it has not expired or been revoked
91
     *
92
     * @return bool
93
     */
94 6
    private function isTokenValid(Token $token)
95
    {
96 6
        return $this->verifyToken($token) && !$this->isTokenExpired($token) && !$this->isTokenRevoked($token);
97
    }
98
99
    /**
100
     * Validate the JWT token.
101
     *
102
     * @param Token $token
103
     *
104
     * @return bool
105
     */
106 6
    private function verifyToken(Token $token)
107
    {
108 6
        $keychain = new Keychain();
109 6
        $key = $keychain->getPrivateKey($this->privateKey->getKeyPath(), $this->privateKey->getPassPhrase());
110
111 6
        return $token->verify(new Sha256, $key->getContent());
112
    }
113
114
    /**
115
     * Ensure access token hasn't expired
116
     *
117
     * @param Token $token
118
     *
119
     * @return bool
120
     */
121 5
    private function isTokenExpired(Token $token)
122
    {
123 5
        $data = new ValidationData(time());
124
125 5
        return !$token->validate($data);
126
    }
127
128
    /**
129
     * Check if the given access token is revoked.
130
     *
131
     * @param Token $token
132
     *
133
     * @return bool
134
     */
135 4
    private function isTokenRevoked(Token $token)
136
    {
137 4
        return $this->accessTokenRepository->isAccessTokenRevoked($token->getClaim('jti'));
138
    }
139
140
    /**
141
     * Create active introspection response.
142
     *
143
     * @param Token $token
144
     *
145
     * @return IntrospectionResponse
146
     */
147 3
    private function setTokenOnResponse(Token $token, IntrospectionResponse $responseType)
148
    {
149 3
        $responseType->setToken($token);
150
151 3
        return $responseType;
152
    }
153
}
154