Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
74.19% covered (warning)
74.19%
23 / 31
62.50% covered (warning)
62.50%
5 / 8
CRAP
0.00% covered (danger)
0.00%
0 / 1
AccessTokenRequestValidator
74.19% covered (warning)
74.19%
23 / 31
62.50% covered (warning)
62.50%
5 / 8
18.87
0.00% covered (danger)
0.00%
0 / 1
 withLtiProvider
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 withRole
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 validate
70.00% covered (warning)
70.00%
14 / 20
0.00% covered (danger)
0.00%
0 / 1
8.32
 withValidator
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getAccessTokenRequestValidator
66.67% covered (warning)
66.67%
2 / 3
0.00% covered (danger)
0.00%
0 / 1
2.15
 getRegistrationRepository
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getLtiProviderService
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 isSameLtiProvider
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3/**
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; under version 2
7 * of the License (non-upgradable).
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17 *
18 * Copyright (c) 2020 (original work) Open Assessment Technologies SA;
19 */
20
21declare(strict_types=1);
22
23namespace oat\taoLti\models\classes\Security;
24
25use OAT\Library\Lti1p3Core\Registration\RegistrationRepositoryInterface;
26use OAT\Library\Lti1p3Core\Security\OAuth2\Validator\RequestAccessTokenValidator as Lti1p3AccessTokenRequestValidator;
27use OAT\Library\Lti1p3Core\Security\OAuth2\Validator\RequestAccessTokenValidatorInterface;
28use oat\oatbox\service\ConfigurableService;
29use oat\taoLti\models\classes\LtiProvider\InvalidLtiProviderException;
30use oat\taoLti\models\classes\LtiProvider\LtiProvider;
31use oat\taoLti\models\classes\LtiProvider\LtiProviderService;
32use oat\taoLti\models\classes\Platform\Repository\Lti1p3RegistrationRepository;
33use oat\taoLti\models\classes\Platform\Service\AccessTokenRequestValidatorInterface;
34use Psr\Http\Message\ServerRequestInterface;
35use tao_models_classes_UserException;
36
37class AccessTokenRequestValidator extends ConfigurableService implements AccessTokenRequestValidatorInterface
38{
39    /** @var Lti1p3AccessTokenRequestValidator */
40    private $validator;
41
42    /** @var LtiProvider */
43    private $ltiProvider;
44
45    /** @var string */
46    private $role;
47
48    public function withLtiProvider(LtiProvider $ltiProvider): AccessTokenRequestValidatorInterface
49    {
50        $this->ltiProvider = $ltiProvider;
51
52        return $this;
53    }
54
55    public function withRole(string $role): AccessTokenRequestValidatorInterface
56    {
57        $this->role = $role;
58
59        return $this;
60    }
61
62    /**
63     * @throws InvalidLtiProviderException
64     * @throws tao_models_classes_UserException
65     */
66    public function validate(ServerRequestInterface $request): void
67    {
68        $allowedScopes = $this->role !== null ? [$this->role] : [];
69        $result = $this->getAccessTokenRequestValidator()->validate($request, $allowedScopes);
70
71        if ($result->hasError() || $result->getRegistration() === null) {
72            throw new tao_models_classes_UserException(
73                sprintf('Access Token Validation failed. %s', $result->getError())
74            );
75        }
76
77        if ($this->ltiProvider !== null) {
78            $requestClientId = $result->getRegistration()->getClientId();
79            $ltiProvider = $this->getLtiProviderService()->searchByToolClientId(
80                $requestClientId
81            );
82
83            if ($ltiProvider === null) {
84                throw new InvalidLtiProviderException(
85                    sprintf(
86                        'Lti provider with client id %s does not exist',
87                        $requestClientId
88                    )
89                );
90            }
91
92            if (!$this->isSameLtiProvider($ltiProvider)) {
93                throw new InvalidLtiProviderException('Lti provider from registration is not matching delivery');
94            }
95        }
96    }
97
98    public function withValidator(RequestAccessTokenValidatorInterface $validator): void
99    {
100        $this->validator = $validator;
101    }
102
103    private function getAccessTokenRequestValidator(): RequestAccessTokenValidatorInterface
104    {
105        if (!$this->validator) {
106            $this->validator = new Lti1p3AccessTokenRequestValidator($this->getRegistrationRepository());
107        }
108
109        return $this->validator;
110    }
111
112    private function getRegistrationRepository(): RegistrationRepositoryInterface
113    {
114        return $this->getServiceLocator()->get(Lti1p3RegistrationRepository::class);
115    }
116
117    private function getLtiProviderService(): LtiProviderService
118    {
119        return $this->getServiceLocator()->get(LtiProviderService::SERVICE_ID);
120    }
121
122    private function isSameLtiProvider(LtiProvider $ltiProvider): bool
123    {
124        return $this->ltiProvider->getId() === $ltiProvider->getId();
125    }
126}