Completed
Pull Request — master (#995)
by
unknown
02:16
created

RevokeTokenHandler::setRefreshTokenRepository()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
1
<?php
2
/**
3
 * @author      Alex Bilbie <[email protected]>
4
 * @copyright   Copyright (c) Alex Bilbie
5
 * @license     http://mit-license.org/
6
 *
7
 * @link        https://github.com/thephpleague/oauth2-server
8
 */
9
10
namespace League\OAuth2\Server;
11
12
use Exception;
13
use InvalidArgumentException;
14
use Lcobucci\JWT\Parser;
15
use Lcobucci\JWT\Signer\Rsa\Sha256;
16
use Lcobucci\JWT\Token;
17
use League\Event\EmitterAwareInterface;
18
use League\Event\EmitterAwareTrait;
19
use League\OAuth2\Server\CryptTrait;
20
use League\OAuth2\Server\RequestValidatorTrait;
21
use League\OAuth2\Server\Exception\OAuthServerException;
22
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
23
use League\OAuth2\Server\Repositories\ClientRepositoryInterface;
24
use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface;
25
use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface;
26
use Psr\Http\Message\ServerRequestInterface;
27
use RuntimeException;
28
29
class RevokeTokenHandler implements EmitterAwareInterface
0 ignored issues
show
Bug introduced by
There is one abstract method getEmitter in this class; you could implement it, or declare this class as abstract.
Loading history...
30
{
31
    use EmitterAwareTrait, CryptTrait, RequestValidatorTrait;
32
33
    /**
34
     * @var ClientRepositoryInterface
35
     */
36
    protected $clientRepository;
37
38
    /**
39
     * @var AccessTokenRepositoryInterface
40
     */
41
    private $accessTokenRepository;
42
43
    /**
44
     * @var RefreshTokenRepositoryInterface
45
     */
46
    private $refreshTokenRepository;
47
48
    /**
49
     * @var bool
50
     */
51
    private $canRevokeAccessTokens;
52
53
    /**
54
     * @var CryptKey
55
     */
56
    protected $publicKey;
57
58
    /**
59
     * New handler instance.
60
     *
61
     * @param RefreshTokenRepositoryInterface $refreshTokenRepository
62
     * @param CryptKey|string                 $publicKey
63
     * @param bool                            $canRevokeAccessTokens
64
     */
65 12
    public function __construct(
66
        RefreshTokenRepositoryInterface $refreshTokenRepository,
67
        $publicKey,
68
        $canRevokeAccessTokens = true
69
    )
70
    {
71 12
        $this->setRefreshTokenRepository($refreshTokenRepository);
72
73 12
        if ($publicKey instanceof CryptKey === false) {
74 1
            $publicKey = new CryptKey($publicKey);
75
        }
76 12
        $this->publicKey = $publicKey;
77
78 12
        $this->canRevokeAccessTokens = $canRevokeAccessTokens;
79 12
    }
80
81
    /**
82
     * @return ClientRepositoryInterface
83
     */
84 12
    public function getClientRepository()
85
    {
86 12
        return $this->clientRepository;
87
    }
88
89
    /**
90
     * @param ClientRepositoryInterface $clientRepository
91
     */
92 12
    public function setClientRepository(ClientRepositoryInterface $clientRepository)
93
    {
94 12
        $this->clientRepository = $clientRepository;
95 12
    }
96
97
    /**
98
     * @param AccessTokenRepositoryInterface $accessTokenRepository
99
     */
100 12
    public function setAccessTokenRepository(AccessTokenRepositoryInterface $accessTokenRepository)
101
    {
102 12
        $this->accessTokenRepository = $accessTokenRepository;
103 12
    }
104
105
    /**
106
     * @param RefreshTokenRepositoryInterface $refreshTokenRepository
107
     */
108 12
    public function setRefreshTokenRepository(RefreshTokenRepositoryInterface $refreshTokenRepository)
109
    {
110 12
        $this->refreshTokenRepository = $refreshTokenRepository;
111 12
    }
112
113
    /**
114
     * Set the public key
115
     *
116
     * @param CryptKey $key
117
     */
118
    public function setPublicKey(CryptKey $key)
119
    {
120
        $this->publicKey = $key;
121
    }
122
123
    /**
124
     * Return the grant identifier that can be used in matching up requests.
125
     *
126
     * @return string
127
     */
128 12
    public function getIdentifier() {
129 12
		return '';
130
	}
131
132
   /**
133
     * Return an revoke token response.
134
     * https://tools.ietf.org/html/rfc7009
135
     *
136
     * @param ServerRequestInterface $request
137
     * @param ResponseTypeInterface  $response
138
     *
139
     * @throws OAuthServerException
140
     *
141
     * @return ResponseTypeInterface
142
     */
143 12
    public function respondToRevokeTokenRequest(ServerRequestInterface $request, ResponseTypeInterface $response)
144
    {
145 12
        if ($request->getMethod() !== 'POST') {
146
            $errorMessage = 'POST method required.';
147
            throw new OAuthServerException($errorMessage, 3, 'invalid_request', 400);
148
        }
149
150 12
        $token = $this->getRequestParameter('token', $request);
151 12
        $hint = $this->getRequestParameter('token_type_hint', $request);
152
153
        // Validate request
154 12
        $client = $this->validateClient($request);
155 12
        $clientId = $client->getIdentifier();
156
157 12
        if (is_null($token)) {
158 1
            return $response;
159
        }
160
161
        // Attempt to read token
162 11
        $accessToken = null;
163 11
        $refreshToken = null;
164 11
        if ($hint === 'refresh_token') {
165 6
            $refreshToken = $this->readAsRefreshToken($token, $clientId);
166 5
            if ($refreshToken === null) {
167 5
                $accessToken = $this->readAsAccessToken($token, $clientId);
168
            }
169
        } else {
170 5
            $accessToken = $this->readAsAccessToken($token, $clientId);
171 5
            if ($accessToken === null) {
172 2
                $refreshToken = $this->readAsRefreshToken($token, $clientId);
173
            }
174
        }
175
176
        // Revoke tokens
177 10
        if ($accessToken !== null) {
178 3
            if (!$this->canRevokeAccessTokens) {
179 1
                $errorMessage = 'The authorization server does not support the revocation of the presented token type';
180 1
                throw new OAuthServerException($errorMessage, 2, 'unsupported_token_type', 400);
181
            }
182 2
            $this->accessTokenRepository->revokeAccessToken($accessToken->getClaim('jti'));
183 7
        } else if ($refreshToken !== null) {
184 5
            $this->refreshTokenRepository->revokeRefreshToken($refreshToken['refresh_token_id']);
185 5
            if ($this->canRevokeAccessTokens) {
186 4
                $this->accessTokenRepository->revokeAccessToken($refreshToken['access_token_id']);
187
            }
188
        }
189
190 9
        return $response;
191
    }
192
193
    /**
194
     * @param string $tokenParam
195
     * @param string $clientId
196
     *
197
     * @return null|Token
198
     */
199 6
    protected function readAsAccessToken($tokenParam, $clientId) {
200 6
        $token = null;
201
        try {
202 6
            $token = (new Parser())->parse($tokenParam);
203
204 3
            if ($token->verify(new Sha256(), $this->publicKey->getKeyPath()) === false) {
205 3
                return null;
206
            }
207 3
        } catch (Exception $exception) {
208
            // JWT couldn't be parsed so ignore
209 3
            return null;
210
        }
211
212 3
        $clientId = $token->getClaim('aud');
213 3
        if ($clientId !== $clientId) {
214
            throw OAuthServerException::invalidClient();
215
        }
216 3
        return $token;
217
    }
218
219
    /**
220
     * @param string $tokenParam
221
     * @param string $clientId
222
     *
223
     * @return null|array
224
     */
225 8
    protected function readAsRefreshToken($tokenParam, $clientId) {
226 8
        $refreshTokenData = null;
227
        try {
228 8
            $refreshToken = $this->decrypt($tokenParam);
229 6
            $refreshTokenData = json_decode($refreshToken, true);
230 2
        } catch (Exception $e) {
231 2
            return null;
232
            // token couldn't be decrypted so ignore
233
        }
234
235 6
        if ($refreshTokenData['client_id'] !== $clientId) {
236 1
            throw OAuthServerException::invalidClient();
237
        }
238 5
        return $refreshTokenData;
239
    }
240
}
241