Passed
Push — master ( 305862...fff288 )
by Rutger
11:51 queued 08:42
created

Oauth2BaseModule::setClientRepository()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

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

702
            /** @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...
703 1
        );
704
705 1
        $builder = $jwtConfiguration->builder()
706 1
            ->permittedFor($clientIdentifier)
707 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

707
            ->issuedBy(/** @scrutinizer ignore-type */ Yii::$app->request->hostInfo)
Loading history...
708 1
            ->issuedAt(new \DateTimeImmutable())
709 1
            ->relatedTo((string)$user->getIdentifier())
710 1
            ->withClaim(
711 1
                Oauth2OidcClaimInterface::OPENID_CONNECT_CLAIM_AUTH_TIME,
712 1
                $user->getLatestAuthenticatedAt()->getTimestamp()
713 1
            );
714
715 1
        if ($nonce) {
716 1
            $builder->withClaim(Oauth2OidcClaimInterface::OPENID_CONNECT_CLAIM_NONCE, $nonce);
717
        }
718
719 1
        if ($expiryDateTime) {
720 1
            $builder->expiresAt($expiryDateTime);
721
        }
722
723 1
        $oidcScopeCollection = $this->getOidcScopeCollection();
724
725 1
        $claims = $oidcScopeCollection->getFilteredClaims($scopeIdentifiers);
726
727 1
        foreach ($claims as $claim) {
728
            if (
729 1
                in_array(
730 1
                    $claim->getIdentifier(),
731 1
                    Oauth2OidcScopeInterface::OPENID_CONNECT_DEFAULT_SCOPE_CLAIMS[
732 1
                        Oauth2OidcScopeInterface::OPENID_CONNECT_SCOPE_OPENID
733 1
                    ]
734 1
                )
735
            ) {
736
                // Skip default claims for OpenID (already set above).
737 1
                continue;
738
            }
739 1
            $claimValue = $user->getOpenIdConnectClaimValue($claim, $this);
740 1
            $builder->withClaim($claim->getIdentifier(), $claimValue);
741
        }
742
743 1
        return $builder->getToken($jwtConfiguration->signer(), $jwtConfiguration->signingKey());
744
    }
745
}
746