Passed
Pull Request — master (#1146)
by Andrew
64:59 queued 30:01
created

BearerTokenValidator::initJwtConfiguration()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 6
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 10
ccs 5
cts 5
cp 1
crap 1
rs 10
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\AuthorizationValidators;
11
12
use DateTimeImmutable;
13
use DateTimeZone;
14
use Lcobucci\Clock\FrozenClock;
15
use Lcobucci\Clock\SystemClock;
16
use Lcobucci\JWT\Configuration;
17
use Lcobucci\JWT\Encoding\CannotDecodeContent;
18
use Lcobucci\JWT\Signer\Key\InMemory;
19
use Lcobucci\JWT\Signer\Key\LocalFileReference;
20
use Lcobucci\JWT\Signer\Rsa\Sha256;
21
use Lcobucci\JWT\Token\InvalidTokenStructure;
22
use Lcobucci\JWT\Token\UnsupportedHeaderFound;
23
use Lcobucci\JWT\Validation\Constraint\SignedWith;
24
use Lcobucci\JWT\Validation\Constraint\ValidAt;
25
use Lcobucci\JWT\Validation\RequiredConstraintsViolated;
26
use League\OAuth2\Server\CryptKey;
27
use League\OAuth2\Server\CryptTrait;
28
use League\OAuth2\Server\Exception\OAuthServerException;
29
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
30
use Psr\Http\Message\ServerRequestInterface;
31
32
class BearerTokenValidator implements AuthorizationValidatorInterface
33
{
34
    use CryptTrait;
35
36
    /**
37
     * @var AccessTokenRepositoryInterface
38
     */
39
    private $accessTokenRepository;
40
41 10
    /**
42
     * @var CryptKey
43 10
     */
44 10
    protected $publicKey;
45
46
    /**
47
     * @var Configuration
48
     */
49
    private $jwtConfiguration;
50
51 10
    /**
52
     * @param AccessTokenRepositoryInterface $accessTokenRepository
53 10
     */
54 10
    public function __construct(AccessTokenRepositoryInterface $accessTokenRepository)
55
    {
56
        $this->accessTokenRepository = $accessTokenRepository;
57
    }
58
59 10
    /**
60
     * Set the public key
61 10
     *
62 1
     * @param CryptKey $key
63
     */
64
    public function setPublicKey(CryptKey $key)
65 9
    {
66 9
        $this->publicKey = $key;
67
68
        $this->initJwtConfiguration();
69
    }
70 9
71
    private function initJwtConfiguration()
72 6
    {
73 5
        $this->jwtConfiguration = Configuration::forSymmetricSigner(
74
            new Sha256(),
75 2
            InMemory::empty()
76 1
        );
77
78
        $this->jwtConfiguration->setValidationConstraints(
79
            new ValidAt(new SystemClock(new DateTimeZone(date_default_timezone_get()))),
80 4
            new SignedWith(new Sha256(), LocalFileReference::file($this->publicKey->getKeyPath()))
81 4
        );
82
    }
83 4
84 4
    /**
85
     * {@inheritdoc}
86 6
     */
87
    public function validateAuthorization(ServerRequestInterface $request)
88 2
    {
89 4
        if ($request->hasHeader('authorization') === false) {
90
            throw OAuthServerException::accessDenied('Missing "Authorization" header');
91 1
        }
92
93
        $header = $request->getHeader('authorization');
94
        $jwt = \trim((string) \preg_replace('/^(?:\s+)?Bearer\s/', '', $header[0]));
95 3
96 1
        try {
97
            // Attempt to parse and validate the JWT
98
            $token = $this->jwtConfiguration->parser()->parse($jwt);
99
100
            /*$this->jwtConfiguration->setValidationConstraints(
101 2
                new SignedWith(
102 2
                    new Sha256(),
103 2
                    LocalFileReference::file($this->publicKey->getKeyPath())
104 2
                )
105
            );*/
106
107
            $constraints = $this->jwtConfiguration->validationConstraints();
108
109
            try {
110
                $this->jwtConfiguration->validator()->assert($token, ...$constraints);
111
            } catch (RequiredConstraintsViolated $exception) {
112
                throw OAuthServerException::accessDenied('Access token could not be verified');
113
            }
114
        } catch (CannotDecodeContent | InvalidTokenStructure | UnsupportedHeaderFound $exception) {
115
            throw OAuthServerException::accessDenied($exception->getMessage(), null, $exception);
116
        }
117
118
        $claims = $token->claims();
119
120
        // Check if token has been revoked
121
        if ($this->accessTokenRepository->isAccessTokenRevoked($claims->get('jti'))) {
122
            throw OAuthServerException::accessDenied('Access token has been revoked');
123
        }
124
125
        // Return the request with additional attributes
126
        return $request
127
            ->withAttribute('oauth_access_token_id', $claims->get('jti'))
128
            ->withAttribute('oauth_client_id', $claims->get('aud'))
129
            ->withAttribute('oauth_user_id', $claims->get('sub'))
130
            ->withAttribute('oauth_scopes', $claims->get('scopes'));
131
    }
132
}
133