AuthorizationServer   A
last analyzed

Complexity

Total Complexity 20

Size/Duplication

Total Lines 184
Duplicated Lines 0 %

Test Coverage

Coverage 90.32%

Importance

Changes 2
Bugs 0 Features 1
Metric Value
eloc 62
dl 0
loc 184
ccs 56
cts 62
cp 0.9032
rs 10
c 2
b 0
f 1
wmc 20

10 Methods

Rating   Name   Duplication   Size   Complexity  
A respondToDeviceAuthorizationRequest() 0 11 3
A enableGrantType() 0 17 2
A validateAuthorizationRequest() 0 9 3
A __construct() 0 22 3
A respondToAccessTokenRequest() 0 17 3
A revokeRefreshTokens() 0 3 1
A getResponseType() 0 11 2
A setDefaultScope() 0 3 1
A completeAuthorizationRequest() 0 7 1
A completeDeviceAuthorizationRequest() 0 4 1
1
<?php
2
3
/**
4
 * @author      Alex Bilbie <[email protected]>
5
 * @copyright   Copyright (c) Alex Bilbie
6
 * @license     http://mit-license.org/
7
 *
8
 * @link        https://github.com/thephpleague/oauth2-server
9
 */
10
11
declare(strict_types=1);
12
13
namespace League\OAuth2\Server;
14
15
use DateInterval;
16
use Defuse\Crypto\Key;
17
use League\OAuth2\Server\EventEmitting\EmitterAwareInterface;
18
use League\OAuth2\Server\EventEmitting\EmitterAwarePolyfill;
19
use League\OAuth2\Server\Exception\OAuthServerException;
20
use League\OAuth2\Server\Grant\GrantTypeInterface;
21
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
22
use League\OAuth2\Server\Repositories\ClientRepositoryInterface;
23
use League\OAuth2\Server\Repositories\ScopeRepositoryInterface;
24
use League\OAuth2\Server\RequestTypes\AuthorizationRequestInterface;
25
use League\OAuth2\Server\ResponseTypes\AbstractResponseType;
26
use League\OAuth2\Server\ResponseTypes\BearerTokenResponse;
27
use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface;
28
use Psr\Http\Message\ResponseInterface;
29
use Psr\Http\Message\ServerRequestInterface;
30
31
class AuthorizationServer implements EmitterAwareInterface
32
{
33
    use EmitterAwarePolyfill;
34
35
    /**
36
     * @var GrantTypeInterface[]
37
     */
38
    protected array $enabledGrantTypes = [];
39
40
    /**
41
     * @var DateInterval[]
42
     */
43
    protected array $grantTypeAccessTokenTTL = [];
44
45
    protected CryptKeyInterface $privateKey;
46
47
    protected CryptKeyInterface $publicKey;
48
49
    protected ResponseTypeInterface $responseType;
50
51
    private string|Key $encryptionKey;
52
53
    private string $defaultScope = '';
54
55
    private bool $revokeRefreshTokens = true;
56
57
    /**
58
     * New server instance
59
     */
60 12
    public function __construct(
61
        private ClientRepositoryInterface $clientRepository,
62
        private AccessTokenRepositoryInterface $accessTokenRepository,
63
        private ScopeRepositoryInterface $scopeRepository,
64
        CryptKeyInterface|string $privateKey,
65
        Key|string $encryptionKey,
66
        ResponseTypeInterface|null $responseType = null
67
    ) {
68 12
        if ($privateKey instanceof CryptKeyInterface === false) {
69 12
            $privateKey = new CryptKey($privateKey);
70
        }
71
72 12
        $this->privateKey = $privateKey;
73 12
        $this->encryptionKey = $encryptionKey;
74
75 12
        if ($responseType === null) {
76 5
            $responseType = new BearerTokenResponse();
77
        } else {
78 7
            $responseType = clone $responseType;
79
        }
80
81 12
        $this->responseType = $responseType;
82
    }
83
84
    /**
85
     * Enable a grant type on the server
86
     */
87 8
    public function enableGrantType(GrantTypeInterface $grantType, DateInterval|null $accessTokenTTL = null): void
88
    {
89 8
        if ($accessTokenTTL === null) {
90 4
            $accessTokenTTL = new DateInterval('PT1H');
91
        }
92
93 8
        $grantType->setAccessTokenRepository($this->accessTokenRepository);
94 8
        $grantType->setClientRepository($this->clientRepository);
95 8
        $grantType->setScopeRepository($this->scopeRepository);
96 8
        $grantType->setDefaultScope($this->defaultScope);
97 8
        $grantType->setPrivateKey($this->privateKey);
98 8
        $grantType->setEmitter($this->getEmitter());
99 8
        $grantType->setEncryptionKey($this->encryptionKey);
100 8
        $grantType->revokeRefreshTokens($this->revokeRefreshTokens);
101
102 8
        $this->enabledGrantTypes[$grantType->getIdentifier()] = $grantType;
103 8
        $this->grantTypeAccessTokenTTL[$grantType->getIdentifier()] = $accessTokenTTL;
104
    }
105
106
    /**
107
     * Validate an authorization request
108
     *
109
     * @throws OAuthServerException
110
     */
111 3
    public function validateAuthorizationRequest(ServerRequestInterface $request): AuthorizationRequestInterface
112
    {
113 3
        foreach ($this->enabledGrantTypes as $grantType) {
114 2
            if ($grantType->canRespondToAuthorizationRequest($request)) {
115 2
                return $grantType->validateAuthorizationRequest($request);
116
            }
117
        }
118
119 1
        throw OAuthServerException::unsupportedGrantType();
120
    }
121
122
    /**
123
     * Complete an authorization request
124
     */
125 1
    public function completeAuthorizationRequest(
126
        AuthorizationRequestInterface $authRequest,
127
        ResponseInterface $response
128
    ): ResponseInterface {
129 1
        return $this->enabledGrantTypes[$authRequest->getGrantTypeId()]
130 1
            ->completeAuthorizationRequest($authRequest)
131 1
            ->generateHttpResponse($response);
132
    }
133
134
    /**
135
     * Respond to device authorization request
136
     *
137
     * @throws OAuthServerException
138
     */
139 1
    public function respondToDeviceAuthorizationRequest(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
140
    {
141 1
        foreach ($this->enabledGrantTypes as $grantType) {
142 1
            if ($grantType->canRespondToDeviceAuthorizationRequest($request)) {
143 1
                return $grantType
144 1
                    ->respondToDeviceAuthorizationRequest($request)
145 1
                    ->generateHttpResponse($response);
146
            }
147
        }
148
149
        throw OAuthServerException::unsupportedGrantType();
150
    }
151
152
    /**
153
     * Complete a device authorization request
154
     */
155
    public function completeDeviceAuthorizationRequest(string $deviceCode, string $userId, bool $userApproved): void
156
    {
157
        $this->enabledGrantTypes['urn:ietf:params:oauth:grant-type:device_code']
158
          ->completeDeviceAuthorizationRequest($deviceCode, $userId, $userApproved);
159
    }
160
161
    /**
162
     * Return an access token response.
163
     *
164
     * @throws OAuthServerException
165
     */
166 4
    public function respondToAccessTokenRequest(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
167
    {
168 4
        foreach ($this->enabledGrantTypes as $grantType) {
169 4
            if (!$grantType->canRespondToAccessTokenRequest($request)) {
170 1
                continue;
171
            }
172
173 3
            $tokenResponse = $grantType->respondToAccessTokenRequest(
174 3
                $request,
175 3
                $this->getResponseType(),
176 3
                $this->grantTypeAccessTokenTTL[$grantType->getIdentifier()]
177 3
            );
178
179 2
            return $tokenResponse->generateHttpResponse($response);
180
        }
181
182 1
        throw OAuthServerException::unsupportedGrantType();
183
    }
184
185
    /**
186
     * Get the token type that grants will return in the HTTP response.
187
     */
188 6
    protected function getResponseType(): ResponseTypeInterface
189
    {
190 6
        $responseType = clone $this->responseType;
191
192 6
        if ($responseType instanceof AbstractResponseType) {
193 6
            $responseType->setPrivateKey($this->privateKey);
194
        }
195
196 6
        $responseType->setEncryptionKey($this->encryptionKey);
197
198 6
        return $responseType;
199
    }
200
201
    /**
202
     * Set the default scope for the authorization server.
203
     */
204 4
    public function setDefaultScope(string $defaultScope): void
205
    {
206 4
        $this->defaultScope = $defaultScope;
207
    }
208
209
    /**
210
     * Sets whether to revoke refresh tokens or not (for all grant types).
211
     */
212
    public function revokeRefreshTokens(bool $revokeRefreshTokens): void
213
    {
214
        $this->revokeRefreshTokens = $revokeRefreshTokens;
215
    }
216
}
217