Passed
Push — master ( f52d5c...0b49e9 )
by Rutger
03:13
created

Oauth2BaseModule::getAccessTokenRepository()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1
c 1
b 0
f 0
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
cc 1
nc 1
nop 0
crap 1
1
<?php
2
3
namespace rhertogh\Yii2Oauth2Server\base;
4
5
use Lcobucci\JWT\Configuration;
6
use Lcobucci\JWT\Signer\Key\InMemory;
7
use Lcobucci\JWT\Signer\Rsa\Sha256;
8
use League\OAuth2\Server\CryptKey;
9
use rhertogh\Yii2Oauth2Server\components\authorization\Oauth2ClientAuthorizationRequest;
10
use rhertogh\Yii2Oauth2Server\components\authorization\Oauth2ScopeAuthorizationRequest;
11
use rhertogh\Yii2Oauth2Server\components\encryption\Oauth2Encryptor;
12
use rhertogh\Yii2Oauth2Server\components\factories\encryption\Oauth2EncryptionKeyFactory;
13
use rhertogh\Yii2Oauth2Server\components\factories\grants\Oauth2AuthCodeGrantFactory;
14
use rhertogh\Yii2Oauth2Server\components\factories\grants\Oauth2ClientCredentialsGrantFactory;
15
use rhertogh\Yii2Oauth2Server\components\factories\grants\Oauth2ImplicitGrantFactory;
16
use rhertogh\Yii2Oauth2Server\components\factories\grants\Oauth2PasswordGrantFactory;
17
use rhertogh\Yii2Oauth2Server\components\factories\grants\Oauth2PersonalAccessTokenGrantFactory;
18
use rhertogh\Yii2Oauth2Server\components\factories\grants\Oauth2RefreshTokenGrantFactory;
19
use rhertogh\Yii2Oauth2Server\components\openidconnect\claims\Oauth2OidcClaim;
20
use rhertogh\Yii2Oauth2Server\components\openidconnect\scopes\Oauth2OidcScope;
21
use rhertogh\Yii2Oauth2Server\components\openidconnect\scopes\Oauth2OidcScopeCollection;
22
use rhertogh\Yii2Oauth2Server\components\openidconnect\server\Oauth2OidcBearerTokenResponse;
23
use rhertogh\Yii2Oauth2Server\components\repositories\Oauth2AccessTokenRepository;
24
use rhertogh\Yii2Oauth2Server\components\repositories\Oauth2AuthCodeRepository;
25
use rhertogh\Yii2Oauth2Server\components\repositories\Oauth2ClientRepository;
26
use rhertogh\Yii2Oauth2Server\components\repositories\Oauth2RefreshTokenRepository;
27
use rhertogh\Yii2Oauth2Server\components\repositories\Oauth2ScopeRepository;
28
use rhertogh\Yii2Oauth2Server\components\repositories\Oauth2UserRepository;
29
use rhertogh\Yii2Oauth2Server\components\server\grants\Oauth2AuthCodeGrant;
30
use rhertogh\Yii2Oauth2Server\components\server\grants\Oauth2ClientCredentialsGrant;
31
use rhertogh\Yii2Oauth2Server\components\server\grants\Oauth2ImplicitGrant;
32
use rhertogh\Yii2Oauth2Server\components\server\grants\Oauth2PasswordGrant;
33
use rhertogh\Yii2Oauth2Server\components\server\grants\Oauth2PersonalAccessTokenGrant;
34
use rhertogh\Yii2Oauth2Server\components\server\grants\Oauth2RefreshTokenGrant;
35
use rhertogh\Yii2Oauth2Server\components\server\Oauth2AuthorizationServer;
36
use rhertogh\Yii2Oauth2Server\components\server\Oauth2ResourceServer;
37
use rhertogh\Yii2Oauth2Server\controllers\web\Oauth2CertificatesController;
38
use rhertogh\Yii2Oauth2Server\controllers\web\Oauth2ConsentController;
39
use rhertogh\Yii2Oauth2Server\controllers\web\Oauth2OidcController;
40
use rhertogh\Yii2Oauth2Server\controllers\web\Oauth2ServerController;
41
use rhertogh\Yii2Oauth2Server\controllers\web\Oauth2WellKnownController;
42
use rhertogh\Yii2Oauth2Server\interfaces\components\authorization\Oauth2ClientAuthorizationRequestInterface;
43
use rhertogh\Yii2Oauth2Server\interfaces\components\authorization\Oauth2ScopeAuthorizationRequestInterface;
44
use rhertogh\Yii2Oauth2Server\interfaces\components\encryption\Oauth2EncryptorInterface;
45
use rhertogh\Yii2Oauth2Server\interfaces\components\factories\encryption\Oauth2EncryptionKeyFactoryInterface;
46
use rhertogh\Yii2Oauth2Server\interfaces\components\factories\grants\Oauth2AuthCodeGrantFactoryInterface;
47
use rhertogh\Yii2Oauth2Server\interfaces\components\factories\grants\Oauth2ClientCredentialsGrantFactoryInterface;
48
use rhertogh\Yii2Oauth2Server\interfaces\components\factories\grants\Oauth2ImplicitGrantFactoryInterface;
49
use rhertogh\Yii2Oauth2Server\interfaces\components\factories\grants\Oauth2PasswordGrantFactoryInterface;
50
use rhertogh\Yii2Oauth2Server\interfaces\components\factories\grants\Oauth2PersonalAccessTokenGrantFactoryInterface;
51
use rhertogh\Yii2Oauth2Server\interfaces\components\factories\grants\Oauth2RefreshTokenGrantFactoryInterface;
52
use rhertogh\Yii2Oauth2Server\interfaces\components\openidconnect\scope\Oauth2OidcClaimInterface;
53
use rhertogh\Yii2Oauth2Server\interfaces\components\openidconnect\scope\Oauth2OidcScopeCollectionInterface;
54
use rhertogh\Yii2Oauth2Server\interfaces\components\openidconnect\scope\Oauth2OidcScopeInterface;
55
use rhertogh\Yii2Oauth2Server\interfaces\components\openidconnect\server\Oauth2OidcBearerTokenResponseInterface;
56
use rhertogh\Yii2Oauth2Server\interfaces\components\repositories\base\Oauth2RepositoryInterface;
57
use rhertogh\Yii2Oauth2Server\interfaces\components\repositories\Oauth2AccessTokenRepositoryInterface;
58
use rhertogh\Yii2Oauth2Server\interfaces\components\repositories\Oauth2AuthCodeRepositoryInterface;
59
use rhertogh\Yii2Oauth2Server\interfaces\components\repositories\Oauth2ClientRepositoryInterface;
60
use rhertogh\Yii2Oauth2Server\interfaces\components\repositories\Oauth2RefreshTokenRepositoryInterface;
61
use rhertogh\Yii2Oauth2Server\interfaces\components\repositories\Oauth2ScopeRepositoryInterface;
62
use rhertogh\Yii2Oauth2Server\interfaces\components\repositories\Oauth2UserRepositoryInterface;
63
use rhertogh\Yii2Oauth2Server\interfaces\components\server\grants\Oauth2AuthCodeGrantInterface;
64
use rhertogh\Yii2Oauth2Server\interfaces\components\server\grants\Oauth2ClientCredentialsGrantInterface;
65
use rhertogh\Yii2Oauth2Server\interfaces\components\server\grants\Oauth2ImplicitGrantInterface;
66
use rhertogh\Yii2Oauth2Server\interfaces\components\server\grants\Oauth2PasswordGrantInterface;
67
use rhertogh\Yii2Oauth2Server\interfaces\components\server\grants\Oauth2PersonalAccessTokenGrantInterface;
68
use rhertogh\Yii2Oauth2Server\interfaces\components\server\grants\Oauth2RefreshTokenGrantInterface;
69
use rhertogh\Yii2Oauth2Server\interfaces\components\server\Oauth2AuthorizationServerInterface;
70
use rhertogh\Yii2Oauth2Server\interfaces\components\server\Oauth2ResourceServerInterface;
71
use rhertogh\Yii2Oauth2Server\interfaces\controllers\web\Oauth2CertificatesControllerInterface;
72
use rhertogh\Yii2Oauth2Server\interfaces\controllers\web\Oauth2ConsentControllerInterface;
73
use rhertogh\Yii2Oauth2Server\interfaces\controllers\web\Oauth2OidcControllerInterface;
74
use rhertogh\Yii2Oauth2Server\interfaces\controllers\web\Oauth2ServerControllerInterface;
75
use rhertogh\Yii2Oauth2Server\interfaces\controllers\web\Oauth2WellKnownControllerInterface;
76
use rhertogh\Yii2Oauth2Server\interfaces\models\external\user\Oauth2OidcUserInterface;
77
use rhertogh\Yii2Oauth2Server\interfaces\models\Oauth2AccessTokenInterface;
78
use rhertogh\Yii2Oauth2Server\interfaces\models\Oauth2AccessTokenScopeInterface;
79
use rhertogh\Yii2Oauth2Server\interfaces\models\Oauth2AuthCodeInterface;
80
use rhertogh\Yii2Oauth2Server\interfaces\models\Oauth2AuthCodeScopeInterface;
81
use rhertogh\Yii2Oauth2Server\interfaces\models\Oauth2ClientInterface;
82
use rhertogh\Yii2Oauth2Server\interfaces\models\Oauth2ClientScopeInterface;
83
use rhertogh\Yii2Oauth2Server\interfaces\models\Oauth2RefreshTokenInterface;
84
use rhertogh\Yii2Oauth2Server\interfaces\models\Oauth2ScopeInterface;
85
use rhertogh\Yii2Oauth2Server\interfaces\models\Oauth2UserClientInterface;
86
use rhertogh\Yii2Oauth2Server\interfaces\models\Oauth2UserClientScopeInterface;
87
use rhertogh\Yii2Oauth2Server\interfaces\models\queries\Oauth2AccessTokenQueryInterface;
88
use rhertogh\Yii2Oauth2Server\interfaces\models\queries\Oauth2AccessTokenScopeQueryInterface;
89
use rhertogh\Yii2Oauth2Server\interfaces\models\queries\Oauth2AuthCodeQueryInterface;
90
use rhertogh\Yii2Oauth2Server\interfaces\models\queries\Oauth2AuthCodeScopeQueryInterface;
91
use rhertogh\Yii2Oauth2Server\interfaces\models\queries\Oauth2ClientQueryInterface;
92
use rhertogh\Yii2Oauth2Server\interfaces\models\queries\Oauth2ClientScopeQueryInterface;
93
use rhertogh\Yii2Oauth2Server\interfaces\models\queries\Oauth2RefreshTokenQueryInterface;
94
use rhertogh\Yii2Oauth2Server\interfaces\models\queries\Oauth2ScopeQueryInterface;
95
use rhertogh\Yii2Oauth2Server\interfaces\models\queries\Oauth2UserClientQueryInterface;
96
use rhertogh\Yii2Oauth2Server\interfaces\models\queries\Oauth2UserClientScopeQueryInterface;
97
use rhertogh\Yii2Oauth2Server\models\Oauth2AccessToken;
98
use rhertogh\Yii2Oauth2Server\models\Oauth2AccessTokenScope;
99
use rhertogh\Yii2Oauth2Server\models\Oauth2AuthCode;
100
use rhertogh\Yii2Oauth2Server\models\Oauth2AuthCodeScope;
101
use rhertogh\Yii2Oauth2Server\models\Oauth2Client;
102
use rhertogh\Yii2Oauth2Server\models\Oauth2ClientScope;
103
use rhertogh\Yii2Oauth2Server\models\Oauth2RefreshToken;
104
use rhertogh\Yii2Oauth2Server\models\Oauth2Scope;
105
use rhertogh\Yii2Oauth2Server\models\Oauth2UserClient;
106
use rhertogh\Yii2Oauth2Server\models\Oauth2UserClientScope;
107
use rhertogh\Yii2Oauth2Server\models\queries\Oauth2AccessTokenQuery;
108
use rhertogh\Yii2Oauth2Server\models\queries\Oauth2AccessTokenScopeQuery;
109
use rhertogh\Yii2Oauth2Server\models\queries\Oauth2AuthCodeQuery;
110
use rhertogh\Yii2Oauth2Server\models\queries\Oauth2AuthCodeScopeQuery;
111
use rhertogh\Yii2Oauth2Server\models\queries\Oauth2ClientQuery;
112
use rhertogh\Yii2Oauth2Server\models\queries\Oauth2ClientScopeQuery;
113
use rhertogh\Yii2Oauth2Server\models\queries\Oauth2RefreshTokenQuery;
114
use rhertogh\Yii2Oauth2Server\models\queries\Oauth2ScopeQuery;
115
use rhertogh\Yii2Oauth2Server\models\queries\Oauth2UserClientQuery;
116
use rhertogh\Yii2Oauth2Server\models\queries\Oauth2UserClientScopeQuery;
117
use rhertogh\Yii2Oauth2Server\Oauth2Module;
118
use Yii;
119
use yii\base\InvalidCallException;
120
use yii\base\InvalidConfigException;
121
use yii\base\Module;
122
123
/**
124
 * @property Oauth2OidcScopeCollectionInterface|array|callable|string $openIdConnectScopes;
125
 */
126
abstract class Oauth2BaseModule extends Module
127
{
128
    # region Supported grant types.
129
    # Note: These should match League\OAuth2\Server\Grant\GrantTypeInterface::getIdentifier() for their respective type.
130
    /**
131
     * "authorization_code" Grant Type.
132
     * @since 1.0.0
133
     */
134
    public const GRANT_TYPE_IDENTIFIER_AUTH_CODE = 'authorization_code';
135
    /**
136
     * "client_credentials" Grant Type.
137
     * @since 1.0.0
138
     */
139
    public const GRANT_TYPE_IDENTIFIER_CLIENT_CREDENTIALS = 'client_credentials';
140
    /**
141
     * "refresh_token" Grant Type.
142
     * @since 1.0.0
143
     */
144
    public const GRANT_TYPE_IDENTIFIER_REFRESH_TOKEN = 'refresh_token';
145
    /**
146
     * "implicit" Grant Type. Note: This is a legacy Grant Type.
147
     * @since 1.0.0
148
     */
149
    public const GRANT_TYPE_IDENTIFIER_IMPLICIT = 'implicit';
150
    /**
151
     * "password" Grant Type. Note: This is a legacy Grant Type.
152
     * @since 1.0.0
153
     */
154
    public const GRANT_TYPE_IDENTIFIER_PASSWORD = 'password';
155
156
    /**
157
     * "personal_access_token" Grant Type. Note: This is a custom grant type and not part of the Oauth2 specification.
158
     * @since 1.0.0
159
     */
160
    public const GRANT_TYPE_IDENTIFIER_PERSONAL_ACCESS_TOKEN = 'personal_access_token';
161
162
    /**
163
     * Supported grant type identifiers
164
     * @since 1.0.0
165
     */
166
    public const GRANT_TYPE_IDENTIFIERS = [
167
        self::GRANT_TYPE_IDENTIFIER_AUTH_CODE,
168
        self::GRANT_TYPE_IDENTIFIER_CLIENT_CREDENTIALS,
169
        self::GRANT_TYPE_IDENTIFIER_REFRESH_TOKEN,
170
        self::GRANT_TYPE_IDENTIFIER_IMPLICIT,
171
        self::GRANT_TYPE_IDENTIFIER_PASSWORD,
172
        self::GRANT_TYPE_IDENTIFIER_PERSONAL_ACCESS_TOKEN,
173
    ];
174
    # endregion Supported grant types
175
176
    # region Numeric IDs for Supported grant types
177
    /**
178
     * Numeric id for "authorization_code" Grant Type.
179
     * @since 1.0.0
180
     */
181
    public const GRANT_TYPE_AUTH_CODE = 1;
182
    /**
183
     * Numeric id for "client_credentials" Grant Type.
184
     * @since 1.0.0
185
     */
186
    public const GRANT_TYPE_CLIENT_CREDENTIALS = 2;
187
    /**
188
     * Numeric id for "refresh_token" Grant Type.
189
     * @since 1.0.0
190
     */
191
    public const GRANT_TYPE_REFRESH_TOKEN = 4;
192
    /**
193
     * Numeric id for "implicit" Grant Type. Note: This is a legacy Grant Type.
194
     * @since 1.0.0
195
     */
196
    public const GRANT_TYPE_PASSWORD = 1024; // Legacy Grant.
197
    /**
198
     * Numeric id for "password" Grant Type. Note: This is a legacy Grant Type.
199
     * @since 1.0.0
200
     */
201
    public const GRANT_TYPE_IMPLICIT = 2048; // Legacy Grant.
202
    /**
203
     * Numeric id for "personal_access_token" Grant Type.
204
     * Note: This is a custom grant type and not part of the Oauth2 specification.
205
     * @since 1.0.0
206
     */
207
    public const GRANT_TYPE_PERSONAL_ACCESS_TOKEN = 4096;
208
    # endregion Numeric IDs for Supported grant types
209
210
    /**
211
     * Mapping between Grant Type identifier and its numeric id.
212
     * @since 1.0.0
213
     */
214
    public const GRANT_TYPE_MAPPING = [
215
        Oauth2Module::GRANT_TYPE_IDENTIFIER_AUTH_CODE => self::GRANT_TYPE_AUTH_CODE,
216
        Oauth2Module::GRANT_TYPE_IDENTIFIER_CLIENT_CREDENTIALS => self::GRANT_TYPE_CLIENT_CREDENTIALS,
217
        Oauth2Module::GRANT_TYPE_IDENTIFIER_REFRESH_TOKEN => self::GRANT_TYPE_REFRESH_TOKEN,
218
        Oauth2Module::GRANT_TYPE_IDENTIFIER_PASSWORD => self::GRANT_TYPE_PASSWORD, // Legacy Grant.
219
        Oauth2Module::GRANT_TYPE_IDENTIFIER_IMPLICIT => self::GRANT_TYPE_IMPLICIT, // Legacy Grant.
220
        Oauth2Module::GRANT_TYPE_IDENTIFIER_PERSONAL_ACCESS_TOKEN => self::GRANT_TYPE_PERSONAL_ACCESS_TOKEN, // Custom Grant.
221
    ];
222
223
    /**
224
     * Events
225
     */
226
    public const EVENT_BEFORE_CLIENT_AUTHORIZATION = 'Oauth2Server.Client.Authorization.Before';
227
    public const EVENT_BEFORE_AFTER_AUTHORIZATION = 'Oauth2Server.Client.Authorization.After';
228
    public const EVENT_BEFORE_AUTH_CODE_ISSUANCE = 'Oauth2Server.Grant.AuthCode.Issuance.Before';
229
    public const EVENT_AFTER_AUTH_CODE_ISSUANCE = 'Oauth2Server.Grant.AuthCode.Issuance.After';
230
    public const EVENT_BEFORE_ACCESS_TOKEN_ISSUANCE = 'Oauth2Server.Grant.AccessToken.Issuance.Before';
231
    public const EVENT_AFTER_ACCESS_TOKEN_ISSUANCE = 'Oauth2Server.Grant.AccessToken.Issuance.After';
232
    public const EVENT_BEFORE_REFRESH_TOKEN_ISSUANCE = 'Oauth2Server.Grant.RefreshToken.Issuance.Before';
233
    public const EVENT_AFTER_REFRESH_TOKEN_ISSUANCE = 'Oauth2Server.Grant.RefreshToken.Issuance.After';
234
235
    /**
236
     * Never show  User Account Selection for OpenID Connect.
237
     * @since 1.0.0
238
     */
239
    public const USER_ACCOUNT_SELECTION_DISABLED = 0;
240
    /**
241
     * Show User Account Selection upon client request for OpenID Connect.
242
     * @since 1.0.0
243
     */
244
    public const USER_ACCOUNT_SELECTION_UPON_CLIENT_REQUEST = 1;
245
    /**
246
     * Always show User Account Selection for OpenID Connect.
247
     * @since 1.0.0
248
     */
249
    public const USER_ACCOUNT_SELECTION_ALWAYS = 2;
250
251
    /**
252
     * Human-readable name for user account selection options.
253
     * @since 1.0.0
254
     */
255
    public const USER_ACCOUNT_SELECTION_NAMES = [
256
        self::USER_ACCOUNT_SELECTION_DISABLED => 'disabled',
257
        self::USER_ACCOUNT_SELECTION_UPON_CLIENT_REQUEST => 'upon_client_request',
258
        self::USER_ACCOUNT_SELECTION_ALWAYS => 'always',
259
    ];
260
261
    /**
262
     * Default factory interface per grant type
263
     * @since 1.0.0
264
     */
265
    protected const DEFAULT_GRANT_TYPE_FACTORIES = [
266
        self::GRANT_TYPE_AUTH_CODE => Oauth2AuthCodeGrantFactoryInterface::class,
267
        self::GRANT_TYPE_CLIENT_CREDENTIALS => Oauth2ClientCredentialsGrantFactoryInterface::class,
268
        self::GRANT_TYPE_REFRESH_TOKEN => Oauth2RefreshTokenGrantFactoryInterface::class,
269
        self::GRANT_TYPE_IMPLICIT => Oauth2ImplicitGrantFactoryInterface::class, // Legacy Grant.
270
        self::GRANT_TYPE_PASSWORD => Oauth2PasswordGrantFactoryInterface::class, // Legacy Grant.
271
        self::GRANT_TYPE_PERSONAL_ACCESS_TOKEN => Oauth2PersonalAccessTokenGrantFactoryInterface::class, // Custom Grant.
272
    ];
273
274
    /**
275
     * Default mapping for interfaces
276
     * @since 1.0.0
277
     */
278
    protected const DEFAULT_INTERFACE_IMPLEMENTATIONS = [
279
        # Repositories
280
        Oauth2AccessTokenRepositoryInterface::class => Oauth2AccessTokenRepository::class,
281
        Oauth2AuthCodeRepositoryInterface::class => Oauth2AuthCodeRepository::class,
282
        Oauth2ClientRepositoryInterface::class => Oauth2ClientRepository::class,
283
        Oauth2RefreshTokenRepositoryInterface::class => Oauth2RefreshTokenRepository::class,
284
        Oauth2ScopeRepositoryInterface::class => Oauth2ScopeRepository::class,
285
        Oauth2UserRepositoryInterface::class => Oauth2UserRepository::class,
286
        # Models
287
        Oauth2AccessTokenInterface::class => Oauth2AccessToken::class,
288
        Oauth2AccessTokenScopeInterface::class => Oauth2AccessTokenScope::class,
289
        Oauth2AuthCodeInterface::class => Oauth2AuthCode::class,
290
        Oauth2AuthCodeScopeInterface::class => Oauth2AuthCodeScope::class,
291
        Oauth2ClientInterface::class => Oauth2Client::class,
292
        Oauth2ClientScopeInterface::class => Oauth2ClientScope::class,
293
        Oauth2RefreshTokenInterface::class => Oauth2RefreshToken::class,
294
        Oauth2ScopeInterface::class => Oauth2Scope::class,
295
        Oauth2UserClientInterface::class => Oauth2UserClient::class,
296
        Oauth2UserClientScopeInterface::class => Oauth2UserClientScope::class,
297
        # Queries
298
        Oauth2AccessTokenQueryInterface::class => Oauth2AccessTokenQuery::class,
299
        Oauth2AccessTokenScopeQueryInterface::class => Oauth2AccessTokenScopeQuery::class,
300
        Oauth2AuthCodeQueryInterface::class => Oauth2AuthCodeQuery::class,
301
        Oauth2AuthCodeScopeQueryInterface::class => Oauth2AuthCodeScopeQuery::class,
302
        Oauth2ClientQueryInterface::class => Oauth2ClientQuery::class,
303
        Oauth2ClientScopeQueryInterface::class => Oauth2ClientScopeQuery::class,
304
        Oauth2RefreshTokenQueryInterface::class => Oauth2RefreshTokenQuery::class,
305
        Oauth2ScopeQueryInterface::class => Oauth2ScopeQuery::class,
306
        Oauth2UserClientQueryInterface::class => Oauth2UserClientQuery::class,
307
        Oauth2UserClientScopeQueryInterface::class => Oauth2UserClientScopeQuery::class,
308
        # Factories
309
        Oauth2AuthCodeGrantFactoryInterface::class => Oauth2AuthCodeGrantFactory::class,
310
        Oauth2ClientCredentialsGrantFactoryInterface::class => Oauth2ClientCredentialsGrantFactory::class,
311
        Oauth2RefreshTokenGrantFactoryInterface::class => Oauth2RefreshTokenGrantFactory::class,
312
        Oauth2ImplicitGrantFactoryInterface::class => Oauth2ImplicitGrantFactory::class,
313
        Oauth2PasswordGrantFactoryInterface::class => Oauth2PasswordGrantFactory::class,
314
        Oauth2PersonalAccessTokenGrantFactoryInterface::class => Oauth2PersonalAccessTokenGrantFactory::class,
315
        Oauth2EncryptionKeyFactoryInterface::class => Oauth2EncryptionKeyFactory::class,
316
        # Controllers
317
        Oauth2ServerControllerInterface::class => Oauth2ServerController::class,
318
        Oauth2ConsentControllerInterface::class => Oauth2ConsentController::class,
319
        Oauth2WellKnownControllerInterface::class => Oauth2WellKnownController::class,
320
        Oauth2CertificatesControllerInterface::class => Oauth2CertificatesController::class,
321
        Oauth2OidcControllerInterface::class => Oauth2OidcController::class,
322
        # Components (Server)
323
        Oauth2AuthorizationServerInterface::class => Oauth2AuthorizationServer::class,
324
        Oauth2ResourceServerInterface::class => Oauth2ResourceServer::class,
325
        # Components (Server Grants)
326
        Oauth2AuthCodeGrantInterface::class => Oauth2AuthCodeGrant::class,
327
        Oauth2ClientCredentialsGrantInterface::class => Oauth2ClientCredentialsGrant::class,
328
        Oauth2ImplicitGrantInterface::class => Oauth2ImplicitGrant::class,
329
        Oauth2PasswordGrantInterface::class => Oauth2PasswordGrant::class,
330
        Oauth2RefreshTokenGrantInterface::class => Oauth2RefreshTokenGrant::class,
331
        Oauth2PersonalAccessTokenGrantInterface::class => Oauth2PersonalAccessTokenGrant::class,
332
        # Components (OpenID Connect)
333
        Oauth2OidcScopeCollectionInterface::class => Oauth2OidcScopeCollection::class,
334
        Oauth2OidcScopeInterface::class => Oauth2OidcScope::class,
335
        Oauth2OidcClaimInterface::class => Oauth2OidcClaim::class,
336
        Oauth2OidcBearerTokenResponseInterface::class => Oauth2OidcBearerTokenResponse::class,
337
        # Components (Misc)
338
        Oauth2EncryptorInterface::class => Oauth2Encryptor::class,
339
        Oauth2ClientAuthorizationRequestInterface::class => Oauth2ClientAuthorizationRequest::class,
340
        Oauth2ScopeAuthorizationRequestInterface::class => Oauth2ScopeAuthorizationRequest::class,
341
    ];
342
343
    /**
344
     * Cache for the Repositories
345
     * @var Oauth2RepositoryInterface[]
346
     * @since 1.0.0
347
     */
348
    protected $_repositories;
349
350
    /**
351
     * Claims for the current request
352
     * @var mixed[]
353
     * @since 1.0.0
354
     */
355
    protected $_oauthClaims;
356
357
    /**
358
     * Configuration for the enabled OpenID Connect scopes.
359
     * @var Oauth2OidcScopeCollectionInterface|array|callable|string
360
     * @since 1.0.0
361
     */
362
    protected $_openIdConnectScopes = Oauth2OidcScopeCollectionInterface::OPENID_CONNECT_DEFAULT_SCOPES;
363
364
    /**
365
     * Cache for the OpenID Connect scope collection.
366
     * @var Oauth2OidcScopeCollectionInterface|null
367
     * @since 1.0.0
368
     */
369
    protected $_oidcScopeCollection = null;
370
371
    //////////////////////////
372
    /// Abstract Functions ///
373
    //////////////////////////
374
375
    /**
376
     * @return Oauth2OidcScopeCollectionInterface The supported scopes for OpenID Connect
377
     * @since 1.0.0
378
     */
379
    abstract public function getOidcScopeCollection();
380
381
    /**
382
     * Get a specific claim from an authorized Request
383
     * @param string $attribute
384
     * @param mixed|null $default
385
     * @return mixed|null The value of the claim or the $default value if not set.
386
     * @throws InvalidCallException
387
     * @since 1.0.0
388
     */
389
    abstract protected function getRequestOauthClaim($attribute, $default = null);
390
391
392
    ////////////////////////
393
    /// Static Functions ///
394
    ////////////////////////
395
396
    /**
397
     * Convert a grant type identifier to its numeric id
398
     * @param string $grantTypeIdentifier
399
     * @return int|null
400
     * @since 1.0.0
401
     */
402 1
    public static function getGrantTypeId($grantTypeIdentifier)
403
    {
404 1
        return static::GRANT_TYPE_MAPPING[$grantTypeIdentifier] ?? null;
405
    }
406
407
    /**
408
     * Convert a numeric grant type id to its string identifier
409
     * @param int $grantTypeId
410
     * @return int|null
411
     * @since 1.0.0
412
     */
413 1
    public static function getGrantTypeIdentifier($grantTypeId)
414
    {
415 1
        return array_flip(static::GRANT_TYPE_MAPPING)[$grantTypeId] ?? null;
416
    }
417
418
    /**
419
     * Convert Grant Type IDs to an array of their identifiers
420
     * @param int $grantTypeIDs
421
     * @return array
422
     */
423
    public static function getGrantTypeIdentifiers($grantTypeIDs)
424
    {
425
        $identifiers = [];
426
        foreach (static::GRANT_TYPE_MAPPING as $identifier => $id) {
427
            if ($grantTypeIDs & $id) {
428
                $identifiers[] = $identifier;
429
            }
430
        }
431
        return $identifiers;
432
    }
433
434
    /////////////////////////
435
    /// Getters & Setters ///
436
    /////////////////////////
437
438
    /**
439
     * @return Oauth2AccessTokenRepositoryInterface The Access Token Repository
440
     * @since 1.0.0
441
     */
442 6
    public function getAccessTokenRepository(): Oauth2AccessTokenRepositoryInterface
443
    {
444 6
        return $this->getRepository(Oauth2AccessTokenRepositoryInterface::class);
445
    }
446
447
    /**
448
     * @return Oauth2AuthCodeRepositoryInterface The Auth Code Repository
449
     * @since 1.0.0
450
     */
451 6
    public function getAuthCodeRepository(): Oauth2AuthCodeRepositoryInterface
452
    {
453 6
        return $this->getRepository(Oauth2AuthCodeRepositoryInterface::class);
454
    }
455
456
    /**
457
     * @return Oauth2ClientRepositoryInterface The Client Repository
458
     * @since 1.0.0
459
     */
460 5
    public function getClientRepository(): Oauth2ClientRepositoryInterface
461
    {
462 5
        return $this->getRepository(Oauth2ClientRepositoryInterface::class);
463
    }
464
465
    /**
466
     * @return Oauth2RefreshTokenRepositoryInterface The Refresh Token Repository
467
     * @since 1.0.0
468
     */
469 8
    public function getRefreshTokenRepository(): Oauth2RefreshTokenRepositoryInterface
470
    {
471 8
        return $this->getRepository(Oauth2RefreshTokenRepositoryInterface::class);
472
    }
473
474
    /**
475
     * @return Oauth2ScopeRepositoryInterface The Scope Repository
476
     * @since 1.0.0
477
     */
478 5
    public function getScopeRepository(): Oauth2ScopeRepositoryInterface
479
    {
480 5
        return $this->getRepository(Oauth2ScopeRepositoryInterface::class);
481
    }
482
483
    /**
484
     * @return Oauth2UserRepositoryInterface The User Repository
485
     * @since 1.0.0
486
     */
487 7
    public function getUserRepository(): Oauth2UserRepositoryInterface
488
    {
489 7
        return $this->getRepository(Oauth2UserRepositoryInterface::class);
490
    }
491
492
    /**
493
     * Get a repository by class.
494
     * @template T of Oauth2RepositoryInterface
495
     * @param class-string<T> $class
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string<T> at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string<T>.
Loading history...
496
     * @return T
497
     * @throws \yii\base\InvalidConfigException
498
     * @since 1.0.0
499
     */
500 14
    protected function getRepository($class)
501
    {
502 14
        if (empty($this->_repositories[$class])) {
503 14
            $this->_repositories[$class] = Yii::createObject($class);
504 14
            $this->_repositories[$class]->setModule($this);
505
        }
506 14
        return $this->_repositories[$class];
507
    }
508
509
    /**
510
     * Get the Oauth 'access_token_id' claim.
511
     * @return string|null
512
     * @see validateAuthenticatedRequest()
513
     * @since 1.0.0
514
     */
515 2
    public function getRequestOauthAccessTokenIdentifier()
516
    {
517 2
        return $this->getRequestOauthClaim('oauth_access_token_id');
518
    }
519
520
    /**
521
     * Get the Oauth 'client_id' claim.
522
     * @return string
523
     * @see validateAuthenticatedRequest()
524
     * @since 1.0.0
525
     */
526 1
    public function getRequestOauthClientIdentifier()
527
    {
528 1
        return $this->getRequestOauthClaim('oauth_client_id');
529
    }
530
531
    /**
532
     * Get the Oauth 'user_id' claim.
533
     * @return mixed|null
534
     * @see validateAuthenticatedRequest()
535
     * @since 1.0.0
536
     */
537 1
    public function getRequestOauthUserId()
538
    {
539 1
        return $this->getRequestOauthClaim('oauth_user_id');
540
    }
541
542
    /**
543
     * Get the Oauth 'scopes' claim.
544
     * @return string[]
545
     * @see validateAuthenticatedRequest()
546
     * @since 1.0.0
547
     */
548 2
    public function getRequestOauthScopeIdentifiers()
549
    {
550 2
        return $this->getRequestOauthClaim('oauth_scopes', []);
551
    }
552
553
    /**
554
     * Check if the Request has the specified scope.
555
     * @param string $scopeIdentifier
556
     * @param bool $strict If strict is `false` and the user is not authenticated via Oauth, return true.
557
     * @return bool
558
     * @see validateAuthenticatedRequest()
559
     * @since 1.0.0
560
     */
561 1
    public function requestHasScope($scopeIdentifier, $strict = true)
562
    {
563 1
        if (!$strict && ($this->getRequestOauthAccessTokenIdentifier() === null)) {
564
            //If not strict and the user is not authenticated via Oauth, allow the scope.
565 1
            return true;
566
        }
567 1
        return in_array($scopeIdentifier, $this->getRequestOauthScopeIdentifiers());
568
    }
569
570
    /**
571
     * Get the configuration for the enabled OpenID Connect scopes.
572
     * @return Oauth2OidcScopeCollectionInterface|array|callable|string
573
     * @see getOidcScopeCollection()
574
     * @since 1.0.0
575
     */
576 3
    public function getOpenIdConnectScopes()
577
    {
578 3
        return $this->_openIdConnectScopes;
579
    }
580
581
    /**
582
     * Set the configuration for the enabled OpenID Connect scopes.
583
     * @return $this
584
     * @see getOidcScopeCollection()
585
     * @since 1.0.0
586
     */
587 2
    public function setOpenIdConnectScopes($openIdConnectScopes)
588
    {
589 2
        $this->_openIdConnectScopes = $openIdConnectScopes;
590 2
        $this->_oidcScopeCollection = null;
591 2
        return $this;
592
    }
593
594
    ////////////////////////
595
    /// Public Functions ///
596
    ////////////////////////
597
598
    /**
599
     * Generates a JWT 'id_token' for OpenID Connect
600
     * @param Oauth2OidcUserInterface $user
601
     * @param string $clientIdentifier
602
     * @param CryptKey $privateKey
603
     * @param string $scopeIdentifiers
604
     * @param string|null $nonce
605
     * @param \DateTimeImmutable|null $expiryDateTime
606
     * @return \Lcobucci\JWT\Token\Plain
607
     * @throws InvalidConfigException
608
     * @see getOidcScopeCollection()
609
     */
610 2
    public function generateOpenIdConnectUserClaimsToken(
611
        $user,
612
        $clientIdentifier,
613
        $privateKey,
614
        $scopeIdentifiers,
615
        $nonce = null,
616
        $expiryDateTime = null
617
    ) {
618 2
        if (!($user instanceof Oauth2OidcUserInterface)) {
0 ignored issues
show
introduced by
$user is always a sub-type of rhertogh\Yii2Oauth2Serve...Oauth2OidcUserInterface.
Loading history...
619 1
            throw new InvalidConfigException('In order to support OpenID Connect '
620 1
                . get_class($user) . ' must implement ' . Oauth2OidcUserInterface::class);
621
        }
622
623 1
        $jwtConfiguration = Configuration::forAsymmetricSigner(
624 1
            new Sha256(),
625 1
            InMemory::plainText($privateKey->getKeyContents(), $privateKey->getPassPhrase() ?? ''),
626 1
            InMemory::empty(),
0 ignored issues
show
Deprecated Code introduced by
The function Lcobucci\JWT\Signer\Key\InMemory::empty() has been deprecated: Deprecated since v4.3 ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

626
            /** @scrutinizer ignore-deprecated */ InMemory::empty(),

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
627 1
        );
628
629 1
        $builder = $jwtConfiguration->builder()
630 1
            ->permittedFor($clientIdentifier)
631 1
            ->issuedBy(Yii::$app->request->hostInfo)
0 ignored issues
show
Bug introduced by
It seems like Yii::app->request->hostInfo can also be of type null; however, parameter $issuer of Lcobucci\JWT\Builder::issuedBy() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

631
            ->issuedBy(/** @scrutinizer ignore-type */ Yii::$app->request->hostInfo)
Loading history...
632 1
            ->issuedAt(new \DateTimeImmutable())
633 1
            ->relatedTo((string)$user->getIdentifier())
634 1
            ->withClaim(
635 1
                Oauth2OidcClaimInterface::OPENID_CONNECT_CLAIM_AUTH_TIME,
636 1
                $user->getLatestAuthenticatedAt()->getTimestamp()
637 1
            );
638
639 1
        if ($nonce) {
640 1
            $builder->withClaim(Oauth2OidcClaimInterface::OPENID_CONNECT_CLAIM_NONCE, $nonce);
641
        }
642
643 1
        if ($expiryDateTime) {
644 1
            $builder->expiresAt($expiryDateTime);
645
        }
646
647 1
        $oidcScopeCollection = $this->getOidcScopeCollection();
648
649 1
        $claims = $oidcScopeCollection->getFilteredClaims($scopeIdentifiers);
0 ignored issues
show
Bug introduced by
$scopeIdentifiers of type string is incompatible with the type string[] expected by parameter $scopeIdentifiers of rhertogh\Yii2Oauth2Serve...ce::getFilteredClaims(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

649
        $claims = $oidcScopeCollection->getFilteredClaims(/** @scrutinizer ignore-type */ $scopeIdentifiers);
Loading history...
650
651 1
        foreach ($claims as $claim) {
652
            if (
653 1
                in_array(
654 1
                    $claim->getIdentifier(),
655 1
                    Oauth2OidcScopeInterface::OPENID_CONNECT_DEFAULT_SCOPE_CLAIMS[
656 1
                        Oauth2OidcScopeInterface::OPENID_CONNECT_SCOPE_OPENID
657 1
                    ]
658 1
                )
659
            ) {
660
                // Skip default claims for OpenID (already set above).
661 1
                continue;
662
            }
663 1
            $claimValue = $user->getOpenIdConnectClaimValue($claim, $this);
664 1
            $builder->withClaim($claim->getIdentifier(), $claimValue);
665
        }
666
667 1
        return $builder->getToken($jwtConfiguration->signer(), $jwtConfiguration->signingKey());
668
    }
669
}
670