Completed
Pull Request — master (#925)
by
unknown
33:06
created

Introspector::isTokenValid()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 3
nc 3
nop 1
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
    public function __construct(
41
        AccessTokenRepositoryInterface $accessTokenRepository,
42
        CryptKey $privateKey,
43
        Parser $parser
44
    ) {
45
        $this->accessTokenRepository = $accessTokenRepository;
46
        $this->privateKey = $privateKey;
47
        $this->parser = $parser;
48
    }
49
50
    /**
51
     * Validate the request
52
     *
53
     * @param ServerRequestInterface $request
54
     *
55
     * @throws OAuthServerException
56
     */
57
    public function validateIntrospectionRequest(ServerRequestInterface $request)
58
    {
59
        if ($request->getMethod() !== 'POST') {
60
            throw OAuthServerException::accessDenied('Invalid request method');
61
        }
62
    }
63
64
    /**
65
     * Return an introspection response.
66
     *
67
     * @param ServerRequestInterface $request
68
     * @param IntrospectionResponse  $responseType
69
     *
70
     * @return IntrospectionResponse
71
     */
72
    public function respondToIntrospectionRequest(
73
        ServerRequestInterface $request,
74
        IntrospectionResponse $responseType
75
    ) {
76
        $jwt = $request->getParsedBody()['token'] ?? null;
77
78
        try {
79
            $token = $this->parser->parse($jwt);
80
        } catch (InvalidArgumentException $e) {
81
            return $responseType;
82
        }
83
84
        return $this->isTokenValid($token) ?
85
            $this->setTokenOnResponse($token, $responseType) :
86
            $responseType;
87
    }
88
89
    /**
90
     * Validate the JWT and make sure it has not expired or been revoked
91
     *
92
     * @return bool
93
     */
94
    private function isTokenValid(Token $token)
95
    {
96
        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
    private function verifyToken(Token $token)
107
    {
108
        $keychain = new Keychain();
109
        $key = $keychain->getPrivateKey($this->privateKey->getKeyPath(), $this->privateKey->getPassPhrase());
110
111
        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
    private function isTokenExpired(Token $token)
122
    {
123
        $data = new ValidationData(time());
124
125
        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
    private function isTokenRevoked(Token $token)
136
    {
137
        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
    private function setTokenOnResponse(Token $token, IntrospectionResponse $responseType)
148
    {
149
        $responseType->setToken($token);
150
151
        return $responseType;
152
    }
153
}
154