1 | <?php |
||||||
2 | |||||||
3 | /** |
||||||
4 | * @link http://www.yiiframework.com/ |
||||||
5 | * @copyright Copyright (c) 2008 Yii Software LLC |
||||||
6 | * @license http://www.yiiframework.com/license/ |
||||||
7 | */ |
||||||
8 | |||||||
9 | namespace rhertogh\Yii2Oauth2Server; |
||||||
10 | |||||||
11 | // phpcs:disable Generic.Files.LineLength.TooLong |
||||||
12 | use Defuse\Crypto\Exception\BadFormatException; |
||||||
13 | use Defuse\Crypto\Exception\EnvironmentIsBrokenException; |
||||||
14 | use GuzzleHttp\Psr7\Response as Psr7Response; |
||||||
15 | use GuzzleHttp\Psr7\ServerRequest as Psr7ServerRequest; |
||||||
16 | use Lcobucci\JWT\Configuration; |
||||||
17 | use Lcobucci\JWT\Signer\Key\InMemory; |
||||||
18 | use Lcobucci\JWT\Signer\Rsa\Sha256; |
||||||
19 | use Lcobucci\JWT\Token; |
||||||
20 | use Lcobucci\JWT\Validation\Constraint\SignedWith; |
||||||
21 | use League\OAuth2\Server\CryptKey; |
||||||
22 | use League\OAuth2\Server\Grant\GrantTypeInterface; |
||||||
23 | use rhertogh\Yii2Oauth2Server\base\Oauth2BaseModule; |
||||||
24 | use rhertogh\Yii2Oauth2Server\components\server\tokens\Oauth2AccessTokenData; |
||||||
25 | use rhertogh\Yii2Oauth2Server\controllers\console\Oauth2ClientController; |
||||||
26 | use rhertogh\Yii2Oauth2Server\controllers\console\Oauth2DebugController; |
||||||
27 | use rhertogh\Yii2Oauth2Server\controllers\console\Oauth2EncryptionController; |
||||||
28 | use rhertogh\Yii2Oauth2Server\controllers\console\Oauth2MigrationsController; |
||||||
29 | use rhertogh\Yii2Oauth2Server\controllers\console\Oauth2PersonalAccessTokenController; |
||||||
30 | use rhertogh\Yii2Oauth2Server\exceptions\Oauth2ServerException; |
||||||
31 | use rhertogh\Yii2Oauth2Server\helpers\DiHelper; |
||||||
32 | use rhertogh\Yii2Oauth2Server\helpers\Psr7Helper; |
||||||
33 | use rhertogh\Yii2Oauth2Server\interfaces\components\authorization\base\Oauth2BaseAuthorizationRequestInterface; |
||||||
34 | use rhertogh\Yii2Oauth2Server\interfaces\components\authorization\client\Oauth2ClientAuthorizationRequestInterface; |
||||||
35 | use rhertogh\Yii2Oauth2Server\interfaces\components\authorization\EndSession\Oauth2EndSessionAuthorizationRequestInterface; |
||||||
36 | use rhertogh\Yii2Oauth2Server\interfaces\components\common\DefaultAccessTokenTtlInterface; |
||||||
37 | use rhertogh\Yii2Oauth2Server\interfaces\components\encryption\Oauth2CryptographerInterface; |
||||||
38 | use rhertogh\Yii2Oauth2Server\interfaces\components\factories\encryption\Oauth2EncryptionKeyFactoryInterface; |
||||||
39 | use rhertogh\Yii2Oauth2Server\interfaces\components\factories\grants\base\Oauth2GrantTypeFactoryInterface; |
||||||
40 | use rhertogh\Yii2Oauth2Server\interfaces\components\openidconnect\request\Oauth2OidcAuthenticationRequestInterface; |
||||||
41 | use rhertogh\Yii2Oauth2Server\interfaces\components\openidconnect\scope\Oauth2OidcScopeCollectionInterface; |
||||||
42 | use rhertogh\Yii2Oauth2Server\interfaces\components\openidconnect\server\responses\Oauth2OidcBearerTokenResponseInterface; |
||||||
43 | use rhertogh\Yii2Oauth2Server\interfaces\components\server\Oauth2AuthorizationServerInterface; |
||||||
44 | use rhertogh\Yii2Oauth2Server\interfaces\components\server\Oauth2ResourceServerInterface; |
||||||
45 | use rhertogh\Yii2Oauth2Server\interfaces\components\server\responses\Oauth2BearerTokenResponseInterface; |
||||||
46 | use rhertogh\Yii2Oauth2Server\interfaces\controllers\web\Oauth2CertificatesControllerInterface; |
||||||
47 | use rhertogh\Yii2Oauth2Server\interfaces\controllers\web\Oauth2ConsentControllerInterface; |
||||||
48 | use rhertogh\Yii2Oauth2Server\interfaces\controllers\web\Oauth2OidcControllerInterface; |
||||||
49 | use rhertogh\Yii2Oauth2Server\interfaces\controllers\web\Oauth2ServerControllerInterface; |
||||||
50 | use rhertogh\Yii2Oauth2Server\interfaces\controllers\web\Oauth2WellKnownControllerInterface; |
||||||
51 | use rhertogh\Yii2Oauth2Server\interfaces\filters\auth\Oauth2HttpBearerAuthInterface; |
||||||
52 | use rhertogh\Yii2Oauth2Server\interfaces\models\base\Oauth2EncryptedStorageInterface; |
||||||
53 | use rhertogh\Yii2Oauth2Server\interfaces\models\external\user\Oauth2OidcUserInterface; |
||||||
54 | use rhertogh\Yii2Oauth2Server\interfaces\models\external\user\Oauth2UserInterface; |
||||||
55 | use rhertogh\Yii2Oauth2Server\interfaces\models\Oauth2ClientInterface; |
||||||
56 | use rhertogh\Yii2Oauth2Server\interfaces\models\Oauth2ScopeInterface; |
||||||
57 | use rhertogh\Yii2Oauth2Server\traits\DefaultAccessTokenTtlTrait; |
||||||
58 | use Yii; |
||||||
59 | use yii\base\BootstrapInterface; |
||||||
60 | use yii\base\InvalidArgumentException; |
||||||
61 | use yii\base\InvalidCallException; |
||||||
62 | use yii\base\InvalidConfigException; |
||||||
63 | use yii\console\Application as ConsoleApplication; |
||||||
64 | use yii\helpers\ArrayHelper; |
||||||
65 | use yii\helpers\Json; |
||||||
66 | use yii\helpers\StringHelper; |
||||||
67 | use yii\helpers\VarDumper; |
||||||
68 | use yii\i18n\PhpMessageSource; |
||||||
69 | use yii\log\Logger; |
||||||
70 | use yii\validators\IpValidator; |
||||||
71 | use yii\web\Application as WebApplication; |
||||||
72 | use yii\web\GroupUrlRule; |
||||||
73 | use yii\web\IdentityInterface; |
||||||
74 | use yii\web\Response; |
||||||
75 | use yii\web\UrlRule; |
||||||
76 | |||||||
77 | // phpcs:enable Generic.Files.LineLength.TooLong |
||||||
78 | |||||||
79 | /** |
||||||
80 | * This is the main module class for the Yii2 Oauth2 Server module. |
||||||
81 | * To use it, include it as a module in the application configuration like the following: |
||||||
82 | * |
||||||
83 | * ~~~ |
||||||
84 | * return [ |
||||||
85 | * 'bootstrap' => ['oauth2'], |
||||||
86 | * 'modules' => [ |
||||||
87 | * 'oauth2' => [ |
||||||
88 | * 'class' => 'rhertogh\Yii2Oauth2Server\Oauth2Module', |
||||||
89 | * // ... Please check docs/guide/start-installation.md further details |
||||||
90 | * ], |
||||||
91 | * ], |
||||||
92 | * ] |
||||||
93 | * ~~~ |
||||||
94 | * |
||||||
95 | * @property \DateInterval|string|null $defaultAccessTokenTTL |
||||||
96 | * @since 1.0.0 |
||||||
97 | */ |
||||||
98 | class Oauth2Module extends Oauth2BaseModule implements BootstrapInterface, DefaultAccessTokenTtlInterface |
||||||
99 | { |
||||||
100 | use DefaultAccessTokenTtlTrait; |
||||||
101 | |||||||
102 | /** |
||||||
103 | * Application type "web": http response. |
||||||
104 | * @since 1.0.0 |
||||||
105 | */ |
||||||
106 | public const APPLICATION_TYPE_WEB = 'web'; |
||||||
107 | /** |
||||||
108 | * Application type "console": cli response. |
||||||
109 | * @since 1.0.0 |
||||||
110 | */ |
||||||
111 | public const APPLICATION_TYPE_CONSOLE = 'console'; |
||||||
112 | /** |
||||||
113 | * Supported Application types. |
||||||
114 | * @since 1.0.0 |
||||||
115 | */ |
||||||
116 | public const APPLICATION_TYPES = [ |
||||||
117 | self::APPLICATION_TYPE_WEB, |
||||||
118 | self::APPLICATION_TYPE_CONSOLE, |
||||||
119 | ]; |
||||||
120 | |||||||
121 | /** |
||||||
122 | * "Authorization Server" Role, please see guide for details. |
||||||
123 | * @since 1.0.0 |
||||||
124 | */ |
||||||
125 | public const SERVER_ROLE_AUTHORIZATION_SERVER = 1; |
||||||
126 | /** |
||||||
127 | * "Resource Server" Role, please see guide for details. |
||||||
128 | * @since 1.0.0 |
||||||
129 | */ |
||||||
130 | public const SERVER_ROLE_RESOURCE_SERVER = 2; |
||||||
131 | |||||||
132 | /** |
||||||
133 | * Required settings when the server role includes Authorization Server |
||||||
134 | * @since 1.0.0 |
||||||
135 | */ |
||||||
136 | protected const REQUIRED_SETTINGS_AUTHORIZATION_SERVER = [ |
||||||
137 | 'codesEncryptionKey', |
||||||
138 | 'storageEncryptionKeys', |
||||||
139 | 'defaultStorageEncryptionKey', |
||||||
140 | 'privateKey', |
||||||
141 | 'publicKey', |
||||||
142 | ]; |
||||||
143 | |||||||
144 | /** |
||||||
145 | * Encrypted Models |
||||||
146 | * |
||||||
147 | * @since 1.0.0 |
||||||
148 | */ |
||||||
149 | protected const ENCRYPTED_MODELS = [ |
||||||
150 | Oauth2ClientInterface::class, |
||||||
151 | ]; |
||||||
152 | |||||||
153 | /** |
||||||
154 | * Required settings when the server role includes Resource Server |
||||||
155 | * @since 1.0.0 |
||||||
156 | */ |
||||||
157 | protected const REQUIRED_SETTINGS_RESOURCE_SERVER = [ |
||||||
158 | 'publicKey', |
||||||
159 | ]; |
||||||
160 | |||||||
161 | /** |
||||||
162 | * Prefix used in session storage of Client Authorization Requests |
||||||
163 | * @since 1.0.0 |
||||||
164 | */ |
||||||
165 | protected const CLIENT_AUTHORIZATION_REQUEST_SESSION_PREFIX = 'OAUTH2_CLIENT_AUTHORIZATION_REQUEST_'; |
||||||
166 | |||||||
167 | /** |
||||||
168 | * Prefix used in session storage of End Session Authorization Requests. |
||||||
169 | * |
||||||
170 | * @since 1.0.0 |
||||||
171 | */ |
||||||
172 | protected const END_SESSION_AUTHORIZATION_REQUEST_SESSION_PREFIX = 'OAUTH2_END_SESSION_AUTHORIZATION_REQUEST_SESSION_PREFIX_'; // phpcs:ignore Generic.Files.LineLength.TooLong |
||||||
173 | |||||||
174 | /** |
||||||
175 | * Controller mapping for the module. Will be parsed on `init()`. |
||||||
176 | * @since 1.0.0 |
||||||
177 | */ |
||||||
178 | protected const CONTROLLER_MAP = [ |
||||||
179 | self::APPLICATION_TYPE_WEB => [ |
||||||
180 | Oauth2ServerControllerInterface::CONTROLLER_NAME => [ |
||||||
181 | 'controller' => Oauth2ServerControllerInterface::class, |
||||||
182 | 'serverRole' => self::SERVER_ROLE_AUTHORIZATION_SERVER, |
||||||
183 | ], |
||||||
184 | Oauth2ConsentControllerInterface::CONTROLLER_NAME => [ |
||||||
185 | 'controller' => Oauth2ConsentControllerInterface::class, |
||||||
186 | 'serverRole' => self::SERVER_ROLE_AUTHORIZATION_SERVER, |
||||||
187 | ], |
||||||
188 | Oauth2WellKnownControllerInterface::CONTROLLER_NAME => [ |
||||||
189 | 'controller' => Oauth2WellKnownControllerInterface::class, |
||||||
190 | 'serverRole' => self::SERVER_ROLE_AUTHORIZATION_SERVER, |
||||||
191 | ], |
||||||
192 | Oauth2CertificatesControllerInterface::CONTROLLER_NAME => [ |
||||||
193 | 'controller' => Oauth2CertificatesControllerInterface::class, |
||||||
194 | 'serverRole' => self::SERVER_ROLE_AUTHORIZATION_SERVER, |
||||||
195 | ], |
||||||
196 | Oauth2OidcControllerInterface::CONTROLLER_NAME => [ |
||||||
197 | 'controller' => Oauth2OidcControllerInterface::class, |
||||||
198 | 'serverRole' => self::SERVER_ROLE_AUTHORIZATION_SERVER, |
||||||
199 | ], |
||||||
200 | ], |
||||||
201 | self::APPLICATION_TYPE_CONSOLE => [ |
||||||
202 | 'migrations' => [ |
||||||
203 | 'controller' => Oauth2MigrationsController::class, |
||||||
204 | 'serverRole' => self::SERVER_ROLE_AUTHORIZATION_SERVER | self::SERVER_ROLE_RESOURCE_SERVER, |
||||||
205 | ], |
||||||
206 | 'client' => [ |
||||||
207 | 'controller' => Oauth2ClientController::class, |
||||||
208 | 'serverRole' => self::SERVER_ROLE_AUTHORIZATION_SERVER, |
||||||
209 | ], |
||||||
210 | 'encryption' => [ |
||||||
211 | 'controller' => Oauth2EncryptionController::class, |
||||||
212 | 'serverRole' => self::SERVER_ROLE_AUTHORIZATION_SERVER, |
||||||
213 | ], |
||||||
214 | 'debug' => [ |
||||||
215 | 'controller' => Oauth2DebugController::class, |
||||||
216 | 'serverRole' => self::SERVER_ROLE_AUTHORIZATION_SERVER | self::SERVER_ROLE_RESOURCE_SERVER, |
||||||
217 | ], |
||||||
218 | 'pat' => [ |
||||||
219 | 'controller' => Oauth2PersonalAccessTokenController::class, |
||||||
220 | 'serverRole' => self::SERVER_ROLE_AUTHORIZATION_SERVER, |
||||||
221 | ] |
||||||
222 | ] |
||||||
223 | ]; |
||||||
224 | |||||||
225 | /** |
||||||
226 | * Offset of Bearer: in Authorization header |
||||||
227 | */ |
||||||
228 | protected const BEARER_TOKEN_OFFSET = 7; |
||||||
229 | |||||||
230 | /** |
||||||
231 | * @inheritdoc |
||||||
232 | */ |
||||||
233 | public $controllerNamespace = __NAMESPACE__ . '\-'; // Set explicitly via $controllerMap in `init()`. |
||||||
234 | |||||||
235 | /** |
||||||
236 | * @var string|null The application type. If `null` the type will be automatically detected. |
||||||
237 | * @see APPLICATION_TYPES |
||||||
238 | */ |
||||||
239 | public $appType = null; |
||||||
240 | |||||||
241 | /** |
||||||
242 | * @var int The Oauth 2.0 Server Roles the module will perform. |
||||||
243 | * @since 1.0.0 |
||||||
244 | */ |
||||||
245 | public $serverRole = self::SERVER_ROLE_AUTHORIZATION_SERVER | self::SERVER_ROLE_RESOURCE_SERVER; |
||||||
246 | |||||||
247 | /** |
||||||
248 | * @var string|null The private key for the server. Can be a string containing the key itself or point to a file. |
||||||
249 | * When pointing to a file it's recommended to use an absolute path prefixed with 'file://' or start with |
||||||
250 | * '@' to use a Yii path alias. |
||||||
251 | * @see $privateKeyPassphrase For setting a passphrase for the private key. |
||||||
252 | * @since 1.0.0 |
||||||
253 | */ |
||||||
254 | public $privateKey = null; |
||||||
255 | |||||||
256 | /** |
||||||
257 | * @var string|null The passphrase for the private key. |
||||||
258 | * @since 1.0.0 |
||||||
259 | */ |
||||||
260 | public $privateKeyPassphrase = null; |
||||||
261 | /** |
||||||
262 | * @var string|null The public key for the server. Can be a string containing the key itself or point to a file. |
||||||
263 | * When pointing to a file it's recommended to use an absolute path prefixed with 'file://' or start with |
||||||
264 | * '@' to use a Yii path alias. |
||||||
265 | * @since 1.0.0 |
||||||
266 | */ |
||||||
267 | public $publicKey = null; |
||||||
268 | |||||||
269 | /** |
||||||
270 | * @var string|null The encryption key for authorization and refresh codes. |
||||||
271 | * @since 1.0.0 |
||||||
272 | */ |
||||||
273 | public $codesEncryptionKey = null; |
||||||
274 | |||||||
275 | /** |
||||||
276 | * @var string[]|string|null The encryption keys for storage like client secrets. |
||||||
277 | * Where the array key is the name of the key, and the value the key itself. E.g. |
||||||
278 | * `['2022-01-01' => 'def00000cb36fd6ed6641e0ad70805b28d....']` |
||||||
279 | * If a string (instead of an array of strings) is specified it will be JSON decoded |
||||||
280 | * it should contain an object where each property name is the name of the key, its value the key itself. E.g. |
||||||
281 | * `{"2022-01-01": "def00000cb36fd6ed6641e0ad70805b28d...."}` |
||||||
282 | * |
||||||
283 | * @since 1.0.0 |
||||||
284 | */ |
||||||
285 | public $storageEncryptionKeys = null; |
||||||
286 | |||||||
287 | /** |
||||||
288 | * @var string|null The index of the default key in storageEncryptionKeys. E.g. 'myKey'. |
||||||
289 | * @since 1.0.0 |
||||||
290 | */ |
||||||
291 | public $defaultStorageEncryptionKey = null; |
||||||
292 | |||||||
293 | /** |
||||||
294 | * @var string|string[]|null IP addresses, CIDR ranges, or range aliases that are allowed to connect over a |
||||||
295 | * non-TLS connection. If `null` or an empty array LTS is always required. |
||||||
296 | * |
||||||
297 | * Warning: Although you can use '*' or 'any' to allow a non-TLS connection from any ip address, |
||||||
298 | * doing so would most likely introduce a security risk and should be done for debugging purposes only! |
||||||
299 | * |
||||||
300 | * @see \yii\validators\IpValidator::$networks for a list of available alliasses. |
||||||
301 | */ |
||||||
302 | public $nonTlsAllowedRanges = 'localhost'; |
||||||
303 | |||||||
304 | /** |
||||||
305 | * @var class-string<Oauth2UserInterface>|null The Identity Class of your application, |
||||||
0 ignored issues
–
show
Documentation
Bug
introduced
by
![]() |
|||||||
306 | * most likely the same as the 'identityClass' of your application's User Component. |
||||||
307 | * @since 1.0.0 |
||||||
308 | */ |
||||||
309 | public $identityClass = null; |
||||||
310 | |||||||
311 | /** |
||||||
312 | * @var null|string Prefix used for url rules. When `null` the module's uniqueId will be used. |
||||||
313 | * @since 1.0.0 |
||||||
314 | */ |
||||||
315 | public $urlRulesPrefix = null; |
||||||
316 | |||||||
317 | /** |
||||||
318 | * @var string URL path for the access token endpoint (will be prefixed with $urlRulesPrefix). |
||||||
319 | * @since 1.0.0 |
||||||
320 | */ |
||||||
321 | public $authorizePath = 'authorize'; |
||||||
322 | |||||||
323 | /** |
||||||
324 | * @var string URL path for the access token endpoint (will be prefixed with $urlRulesPrefix). |
||||||
325 | * @since 1.0.0 |
||||||
326 | */ |
||||||
327 | public $accessTokenPath = 'access-token'; |
||||||
328 | |||||||
329 | /** |
||||||
330 | * @var string URL path for the token revocation endpoint (will be prefixed with $urlRulesPrefix). |
||||||
331 | * @since 1.0.0 |
||||||
332 | */ |
||||||
333 | public $tokenRevocationPath = 'revoke'; |
||||||
334 | |||||||
335 | /** |
||||||
336 | * @var string URL path for the certificates jwks endpoint (will be prefixed with $urlRulesPrefix). |
||||||
337 | * @since 1.0.0 |
||||||
338 | */ |
||||||
339 | public $jwksPath = 'certs'; |
||||||
340 | |||||||
341 | /** |
||||||
342 | * The URL to the page where the user can perform the Client/Scope authorization |
||||||
343 | * (if `null` the build in page will be used). |
||||||
344 | * @return string |
||||||
345 | * @since 1.0.0 |
||||||
346 | * @see $clientAuthorizationPath |
||||||
347 | */ |
||||||
348 | public $clientAuthorizationUrl = null; |
||||||
349 | |||||||
350 | /** |
||||||
351 | * @var string The URL path to the build in page where the user can authorize the Client for the requested Scopes |
||||||
352 | * (will be prefixed with $urlRulesPrefix). |
||||||
353 | * Note: This setting will only be used if $clientAuthorizationUrl is `null`. |
||||||
354 | * @since 1.0.0 |
||||||
355 | * @see $clientAuthorizationView |
||||||
356 | */ |
||||||
357 | public $clientAuthorizationPath = 'authorize-client'; |
||||||
358 | |||||||
359 | /** |
||||||
360 | * @var string The view to use in the "Client Authorization" action for the page where the user can |
||||||
361 | * authorize the Client for the requested Scopes. |
||||||
362 | * Note: This setting will only be used if $clientAuthorizationUrl is `null`. |
||||||
363 | * @since 1.0.0 |
||||||
364 | * @see $clientAuthorizationPath |
||||||
365 | */ |
||||||
366 | public $clientAuthorizationView = 'authorize-client'; |
||||||
367 | |||||||
368 | /** |
||||||
369 | * @var bool Allow clients to invoke token revocation (RFC 7009). |
||||||
370 | * @see https://datatracker.ietf.org/doc/html/rfc7009 |
||||||
371 | */ |
||||||
372 | public $enableTokenRevocation = true; |
||||||
373 | |||||||
374 | /** |
||||||
375 | * @var bool Will the server throw an exception when a Client requests an unknown or unauthorized scope |
||||||
376 | * (would be silently ignored otherwise). |
||||||
377 | * Note: this setting can be overwritten per client. |
||||||
378 | */ |
||||||
379 | public $exceptionOnInvalidScope = false; |
||||||
380 | |||||||
381 | /** |
||||||
382 | * Configuration for `Oauth2Client::getRedirectUrisEnvVarConfig()` fallback (the |
||||||
383 | * Oauth2Client::$envVarConfig['redirectUris'] has precedence). |
||||||
384 | * When configured, environment variables specified in the `Oauth2Client` redirect URI(s) will be substituted with |
||||||
385 | * their values. Please see `EnvironmentHelper::parseEnvVars()` for more details. |
||||||
386 | * |
||||||
387 | * Warning: This setting applies to all clients, for security it's recommended to specify this configuration at the |
||||||
388 | * individual client level via its `envVarConfig` setting. |
||||||
389 | * |
||||||
390 | * @var array{ |
||||||
0 ignored issues
–
show
|
|||||||
391 | * allowList: array, |
||||||
392 | * denyList: array|null, |
||||||
393 | * parseNested: bool, |
||||||
394 | * exceptionWhenNotSet: bool, |
||||||
395 | * exceptionWhenNotAllowed: bool, |
||||||
396 | * }|null |
||||||
397 | * @see Oauth2ClientInterface::setEnvVarConfig() |
||||||
398 | * @see Oauth2ClientInterface::getRedirectUrisEnvVarConfig() |
||||||
399 | * @see \rhertogh\Yii2Oauth2Server\helpers\EnvironmentHelper::parseEnvVars() |
||||||
400 | */ |
||||||
401 | public $clientRedirectUrisEnvVarConfig = null; |
||||||
402 | |||||||
403 | public $userAccountCreationUrl = null; |
||||||
0 ignored issues
–
show
|
|||||||
404 | |||||||
405 | /** |
||||||
406 | * @var string|null The URL path to the OpenID Connect Provider Configuration Information Action. |
||||||
407 | * If set to `null` the endpoint will be disabled. |
||||||
408 | * Note: This path is defined in the |
||||||
409 | * [OpenID Connect Discovery](https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.4) |
||||||
410 | * specification and should normally not be changed. |
||||||
411 | * @since 1.0.0 |
||||||
412 | */ |
||||||
413 | public $openIdConnectProviderConfigurationInformationPath = '.well-known/openid-configuration'; |
||||||
414 | |||||||
415 | /** |
||||||
416 | * @var string The URL path to the OpenID Connect Userinfo Action (will be prefixed with $urlRulesPrefix). |
||||||
417 | * Note: This setting will only be used if $enableOpenIdConnect and $openIdConnectUserinfoEndpoint are `true`. |
||||||
418 | * @since 1.0.0 |
||||||
419 | * @see $openIdConnectUserinfoEndpoint |
||||||
420 | */ |
||||||
421 | public $openIdConnectUserinfoPath = 'oidc/userinfo'; |
||||||
422 | |||||||
423 | /** |
||||||
424 | * @var string The URL path to the OpenID Connect End Session Action (will be prefixed with $urlRulesPrefix). |
||||||
425 | * Note: This setting will only be used if $enableOpenIdConnect and |
||||||
426 | * $openIdConnectRpInitiatedLogoutEndpoint are `true`. |
||||||
427 | * @since 1.0.0 |
||||||
428 | * @see $openIdConnectRpInitiatedLogoutEndpoint |
||||||
429 | * @see https://openid.net/specs/openid-connect-rpinitiated-1_0.html |
||||||
430 | */ |
||||||
431 | public $openIdConnectRpInitiatedLogoutPath = 'oidc/end-session'; |
||||||
432 | |||||||
433 | /** |
||||||
434 | * The URL to the page where the user can perform the End Session (logout) confirmation |
||||||
435 | * (if `null` the build in page will be used). |
||||||
436 | * @return string |
||||||
437 | * @since 1.0.0 |
||||||
438 | * @see $openIdConnectLogoutConfirmationPath |
||||||
439 | */ |
||||||
440 | public $openIdConnectLogoutConfirmationUrl = null; |
||||||
441 | |||||||
442 | /** |
||||||
443 | * @var string The URL path to the build in page where the user can confirm the End Session (logout) request |
||||||
444 | * (will be prefixed with $urlRulesPrefix). |
||||||
445 | * Note: This setting will only be used if $openIdConnectLogoutConfirmationUrl is `null`. |
||||||
446 | * @since 1.0.0 |
||||||
447 | * @see $openIdConnectLogoutConfirmationView |
||||||
448 | */ |
||||||
449 | public $openIdConnectLogoutConfirmationPath = 'confirm-logout'; |
||||||
450 | |||||||
451 | /** |
||||||
452 | * @var string The view to use in the "End Session Authorization" action for the page where the user can |
||||||
453 | * authorize the End Session (logout) request. |
||||||
454 | * Note: This setting will only be used if $openIdConnectLogoutConfirmationUrl is `null`. |
||||||
455 | * @since 1.0.0 |
||||||
456 | * @see $openIdConnectLogoutConfirmationPath |
||||||
457 | */ |
||||||
458 | public $openIdConnectLogoutConfirmationView = 'confirm-logout'; |
||||||
459 | |||||||
460 | |||||||
461 | /** |
||||||
462 | * @var Oauth2GrantTypeFactoryInterface[]|GrantTypeInterface[]|string[]|Oauth2GrantTypeFactoryInterface|GrantTypeInterface|string|callable |
||||||
463 | * The Oauth 2.0 Grant Types that the module will serve. |
||||||
464 | * @since 1.0.0 |
||||||
465 | */ |
||||||
466 | public $grantTypes = []; |
||||||
467 | |||||||
468 | /** |
||||||
469 | * @var bool Should the resource server check for revocation of the access token. |
||||||
470 | * @since 1.0.0 |
||||||
471 | */ |
||||||
472 | public $resourceServerAccessTokenRevocationValidation = true; |
||||||
473 | |||||||
474 | /** |
||||||
475 | * @var bool Enable support for OpenIdvConnect. |
||||||
476 | * @since 1.0.0 |
||||||
477 | */ |
||||||
478 | public $enableOpenIdConnect = false; |
||||||
479 | |||||||
480 | /** |
||||||
481 | * @var bool Enable the .well-known/openid-configuration discovery endpoint. |
||||||
482 | * @since 1.0.0 |
||||||
483 | */ |
||||||
484 | public $enableOpenIdConnectDiscovery = true; |
||||||
485 | |||||||
486 | /** |
||||||
487 | * @var bool include `grant_types_supported` in the OpenIdConnect Discovery. |
||||||
488 | * Note: Since grant types can be specified per client not all clients might support all enabled grant types. |
||||||
489 | * @since 1.0.0 |
||||||
490 | */ |
||||||
491 | public $openIdConnectDiscoveryIncludeSupportedGrantTypes = true; |
||||||
492 | |||||||
493 | /** |
||||||
494 | * @var string URL to include in the OpenID Connect Discovery Service of a page containing |
||||||
495 | * human-readable information that developers might want or need to know when using the OpenID Provider. |
||||||
496 | * @see 'service_documentation' in https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3 |
||||||
497 | * @since 1.0.0 |
||||||
498 | */ |
||||||
499 | public $openIdConnectDiscoveryServiceDocumentationUrl = null; |
||||||
500 | |||||||
501 | /** |
||||||
502 | * @var string|bool A string to a custom userinfo endpoint or `true` to enable the build in endpoint. |
||||||
503 | * @since 1.0.0 |
||||||
504 | * @see $openIdConnectUserinfoPath |
||||||
505 | */ |
||||||
506 | public $openIdConnectUserinfoEndpoint = true; |
||||||
507 | |||||||
508 | /** |
||||||
509 | * @var string|bool A string to a custom logout endpoint or `true` to enable the build in endpoint. |
||||||
510 | * @since 1.0.0 |
||||||
511 | * @see $openIdConnectRpInitiatedLogoutPath |
||||||
512 | * @see https://openid.net/specs/openid-connect-rpinitiated-1_0.html |
||||||
513 | */ |
||||||
514 | public $openIdConnectRpInitiatedLogoutEndpoint = false; |
||||||
515 | |||||||
516 | /** |
||||||
517 | * @var bool Allow access to the "end session" endpoint without user authentication (in the form of the |
||||||
518 | * `id_token_hint` parameter). If enabled the "end session" endpoint will always prompt the user to verify the |
||||||
519 | * logout if no `id_token_hint` is provided and no redirect after logout will be performed. |
||||||
520 | * Note: If disabled the client's `oidc_rp_initiated_logout` will be used |
||||||
521 | * to determine whether to prompt the end-user for logout validation. |
||||||
522 | * @since 1.0.0 |
||||||
523 | * @see $openIdConnectRpInitiatedLogoutPath |
||||||
524 | * @see https://openid.net/specs/openid-connect-rpinitiated-1_0.html |
||||||
525 | */ |
||||||
526 | public $openIdConnectAllowAnonymousRpInitiatedLogout = false; |
||||||
527 | |||||||
528 | /** |
||||||
529 | * Warning! Enabling this setting might introduce privacy concerns since the client could poll for the |
||||||
530 | * online status of a user. |
||||||
531 | * |
||||||
532 | * @var bool If this setting is disabled in case of OpenID Connect Context the Access Token won't include a |
||||||
533 | * Refresh Token when the 'offline_access' scope is not included in the authorization request. |
||||||
534 | * In some cases it might be needed to always include a Refresh Token, in that case enable this setting and |
||||||
535 | * implement the `Oauth2OidcUserSessionStatusInterface` on the User Identity model. |
||||||
536 | * @since 1.0.0 |
||||||
537 | */ |
||||||
538 | public $openIdConnectIssueRefreshTokenWithoutOfflineAccessScope = false; |
||||||
539 | |||||||
540 | /** |
||||||
541 | * @var int The default option for "User Account Selection' when not specified for a client. |
||||||
542 | * @since 1.0.0 |
||||||
543 | */ |
||||||
544 | public $defaultUserAccountSelection = self::USER_ACCOUNT_SELECTION_DISABLED; |
||||||
545 | |||||||
546 | /** |
||||||
547 | * @var bool|null Display exception messages that might leak server details. This could be useful for debugging. |
||||||
548 | * In case of `null` (default) the YII_DEBUG constant will be used. |
||||||
549 | * Warning: Should NOT be enabled in production! |
||||||
550 | * @since 1.0.0 |
||||||
551 | */ |
||||||
552 | public $displayConfidentialExceptionMessages = null; |
||||||
553 | |||||||
554 | /** |
||||||
555 | * @var string|null The namespace with which migrations will be created (and by which they will be located). |
||||||
556 | * Note: The specified namespace must be defined as a Yii alias (e.g. '@app'). |
||||||
557 | * @since 1.0.0 |
||||||
558 | */ |
||||||
559 | public $migrationsNamespace = null; |
||||||
560 | /** |
||||||
561 | * @var string|null Optional prefix used in the name of generated migrations |
||||||
562 | * @since 1.0.0 |
||||||
563 | */ |
||||||
564 | public $migrationsPrefix = null; |
||||||
565 | /** |
||||||
566 | * @var string|array|int|null Sets the file ownership of generated migrations |
||||||
567 | * @see \yii\helpers\BaseFileHelper::changeOwnership() |
||||||
568 | * @since 1.0.0 |
||||||
569 | */ |
||||||
570 | public $migrationsFileOwnership = null; |
||||||
571 | /** |
||||||
572 | * @var int|null Sets the file mode of generated migrations |
||||||
573 | * @see \yii\helpers\BaseFileHelper::changeOwnership() |
||||||
574 | * @since 1.0.0 |
||||||
575 | */ |
||||||
576 | public $migrationsFileMode = null; |
||||||
577 | |||||||
578 | /** |
||||||
579 | * The log level for HTTP Client Errors (HTTP status code 400 - 499). Can be one of the following: |
||||||
580 | * - A log level of `\yii\log\Logger` => LEVEL_ERROR, LEVEL_WARNING, LEVEL_INFO, LEVEL_TRACE. |
||||||
581 | * - `0` => disable logging for HTTP Client Errors |
||||||
582 | * - null => The `YII_DEBUG` constant will be used to determine the log level. |
||||||
583 | * If `true` LEVEL_ERROR will be used, LEVEL_INFO otherwise. |
||||||
584 | * @var int|null |
||||||
585 | * @see \yii\log\Logger |
||||||
586 | */ |
||||||
587 | public $httpClientErrorsLogLevel = null; |
||||||
588 | |||||||
589 | /** |
||||||
590 | * @var Oauth2AuthorizationServerInterface|null Cache for the authorization server |
||||||
591 | * @since 1.0.0 |
||||||
592 | */ |
||||||
593 | protected $_authorizationServer = null; |
||||||
594 | |||||||
595 | /** |
||||||
596 | * @var Oauth2ResourceServerInterface|null Cache for the resource server |
||||||
597 | * @since 1.0.0 |
||||||
598 | */ |
||||||
599 | protected $_resourceServer = null; |
||||||
600 | |||||||
601 | /** |
||||||
602 | * @var Oauth2CryptographerInterface|null Cache for the Oauth2Cryptographer |
||||||
603 | * @since 1.0.0 |
||||||
604 | */ |
||||||
605 | protected $_cryptographer = null; |
||||||
606 | |||||||
607 | /** |
||||||
608 | * @var string|null The authorization header used when the authorization request was validated. |
||||||
609 | * @since 1.0.0 |
||||||
610 | */ |
||||||
611 | protected $_oauthClaimsAuthorizationHeader = null; |
||||||
612 | |||||||
613 | /** |
||||||
614 | * @inheritDoc |
||||||
615 | * @throws InvalidConfigException |
||||||
616 | */ |
||||||
617 | 161 | public function init() |
|||||
618 | { |
||||||
619 | 161 | parent::init(); |
|||||
620 | |||||||
621 | 161 | $app = Yii::$app; |
|||||
622 | |||||||
623 | 161 | if ($app instanceof WebApplication || $this->appType == static::APPLICATION_TYPE_WEB) { |
|||||
624 | 31 | $controllerMap = static::CONTROLLER_MAP[static::APPLICATION_TYPE_WEB]; |
|||||
625 | 161 | } elseif ($app instanceof ConsoleApplication || $this->appType == static::APPLICATION_TYPE_CONSOLE) { |
|||||
0 ignored issues
–
show
|
|||||||
626 | 161 | $controllerMap = static::CONTROLLER_MAP[static::APPLICATION_TYPE_CONSOLE]; |
|||||
627 | 161 | $this->defaultRoute = 'debug'; |
|||||
628 | } else { |
||||||
629 | 1 | throw new InvalidConfigException( |
|||||
630 | 1 | 'Unable to detect application type, configure it manually by setting `$appType`.' |
|||||
631 | 1 | ); |
|||||
632 | } |
||||||
633 | 161 | $controllerMap = array_filter( |
|||||
634 | 161 | $controllerMap, |
|||||
635 | 161 | fn($controllerSettings) => $controllerSettings['serverRole'] & $this->serverRole |
|||||
636 | 161 | ); |
|||||
637 | 161 | $this->controllerMap = ArrayHelper::getColumn($controllerMap, 'controller'); |
|||||
638 | |||||||
639 | 161 | if (empty($this->identityClass)) { |
|||||
640 | 1 | throw new InvalidConfigException('$identityClass must be set.'); |
|||||
641 | 161 | } elseif (!is_a($this->identityClass, Oauth2UserInterface::class, true)) { |
|||||
642 | 1 | throw new InvalidConfigException( |
|||||
643 | 1 | $this->identityClass . ' must implement ' . Oauth2UserInterface::class |
|||||
644 | 1 | ); |
|||||
645 | } |
||||||
646 | |||||||
647 | 161 | foreach (static::DEFAULT_INTERFACE_IMPLEMENTATIONS as $interface => $implementation) { |
|||||
648 | 161 | if (!Yii::$container->has($interface)) { |
|||||
649 | 161 | Yii::$container->set($interface, $implementation); |
|||||
650 | } |
||||||
651 | } |
||||||
652 | |||||||
653 | 161 | if (empty($this->urlRulesPrefix)) { |
|||||
654 | 161 | $this->urlRulesPrefix = $this->uniqueId; |
|||||
655 | } |
||||||
656 | |||||||
657 | 161 | $this->registerTranslations(); |
|||||
658 | } |
||||||
659 | |||||||
660 | /** |
||||||
661 | * @inheritdoc |
||||||
662 | * @throws InvalidConfigException |
||||||
663 | */ |
||||||
664 | 161 | public function bootstrap($app) |
|||||
665 | { |
||||||
666 | if ( |
||||||
667 | 161 | $app instanceof WebApplication |
|||||
668 | 161 | && $this->serverRole & static::SERVER_ROLE_AUTHORIZATION_SERVER |
|||||
669 | ) { |
||||||
670 | 31 | $rules = [ |
|||||
671 | 31 | $this->accessTokenPath => Oauth2ServerControllerInterface::CONTROLLER_NAME |
|||||
672 | 31 | . '/' . Oauth2ServerControllerInterface::ACTION_NAME_ACCESS_TOKEN, |
|||||
673 | 31 | $this->authorizePath => Oauth2ServerControllerInterface::CONTROLLER_NAME |
|||||
674 | 31 | . '/' . Oauth2ServerControllerInterface::ACTION_NAME_AUTHORIZE, |
|||||
675 | 31 | $this->jwksPath => Oauth2CertificatesControllerInterface::CONTROLLER_NAME |
|||||
676 | 31 | . '/' . Oauth2CertificatesControllerInterface::ACTION_NAME_JWKS, |
|||||
677 | 31 | ]; |
|||||
678 | |||||||
679 | 31 | if ($this->enableTokenRevocation) { |
|||||
680 | 31 | $rules[$this->tokenRevocationPath] = Oauth2ServerControllerInterface::CONTROLLER_NAME |
|||||
681 | 31 | . '/' . Oauth2ServerControllerInterface::ACTION_NAME_REVOKE; |
|||||
682 | } |
||||||
683 | |||||||
684 | 31 | if (empty($this->clientAuthorizationUrl)) { |
|||||
685 | 30 | $rules[$this->clientAuthorizationPath] = Oauth2ConsentControllerInterface::CONTROLLER_NAME |
|||||
686 | 30 | . '/' . Oauth2ConsentControllerInterface::ACTION_NAME_AUTHORIZE_CLIENT; |
|||||
687 | } |
||||||
688 | |||||||
689 | 31 | if ($this->enableOpenIdConnect && $this->openIdConnectUserinfoEndpoint === true) { |
|||||
690 | 31 | $rules[$this->openIdConnectUserinfoPath] = |
|||||
691 | 31 | Oauth2OidcControllerInterface::CONTROLLER_NAME |
|||||
692 | 31 | . '/' . Oauth2OidcControllerInterface::ACTION_NAME_USERINFO; |
|||||
693 | } |
||||||
694 | |||||||
695 | 31 | if ($this->enableOpenIdConnect && $this->openIdConnectRpInitiatedLogoutEndpoint === true) { |
|||||
696 | 31 | $rules[$this->openIdConnectRpInitiatedLogoutPath] = |
|||||
697 | 31 | Oauth2OidcControllerInterface::CONTROLLER_NAME |
|||||
698 | 31 | . '/' . Oauth2OidcControllerInterface::ACTION_END_SESSION; |
|||||
699 | |||||||
700 | 31 | if (empty($this->openIdConnectLogoutConfirmationUrl)) { |
|||||
701 | 31 | $rules[$this->openIdConnectLogoutConfirmationPath] = |
|||||
702 | 31 | Oauth2ConsentControllerInterface::CONTROLLER_NAME |
|||||
703 | 31 | . '/' . Oauth2ConsentControllerInterface::ACTION_NAME_AUTHORIZE_END_SESSION; |
|||||
704 | } |
||||||
705 | } |
||||||
706 | |||||||
707 | 31 | $urlManager = $app->getUrlManager(); |
|||||
708 | 31 | $urlManager->addRules([ |
|||||
709 | 31 | Yii::createObject([ |
|||||
710 | 31 | 'class' => GroupUrlRule::class, |
|||||
711 | 31 | 'prefix' => $this->urlRulesPrefix, |
|||||
712 | 31 | 'routePrefix' => $this->id, |
|||||
713 | 31 | 'rules' => $rules, |
|||||
714 | 31 | ]), |
|||||
715 | 31 | ]); |
|||||
716 | |||||||
717 | if ( |
||||||
718 | 31 | $this->enableOpenIdConnect |
|||||
719 | 31 | && $this->enableOpenIdConnectDiscovery |
|||||
720 | 31 | && $this->openIdConnectProviderConfigurationInformationPath |
|||||
721 | ) { |
||||||
722 | 31 | $urlManager->addRules([ |
|||||
723 | 31 | Yii::createObject([ |
|||||
724 | 31 | 'class' => UrlRule::class, |
|||||
725 | 31 | 'pattern' => $this->openIdConnectProviderConfigurationInformationPath, |
|||||
726 | 31 | 'route' => $this->id |
|||||
727 | 31 | . '/' . Oauth2WellKnownControllerInterface::CONTROLLER_NAME |
|||||
728 | 31 | . '/' . Oauth2WellKnownControllerInterface::ACTION_NAME_OPENID_CONFIGURATION, |
|||||
729 | 31 | ]), |
|||||
730 | 31 | ]); |
|||||
731 | } |
||||||
732 | } |
||||||
733 | } |
||||||
734 | |||||||
735 | /** |
||||||
736 | * Registers the translations for the module |
||||||
737 | * @param bool $force Force the setting of the translations (even if they are already defined). |
||||||
738 | * @since 1.0.0 |
||||||
739 | */ |
||||||
740 | 161 | public function registerTranslations($force = false) |
|||||
741 | { |
||||||
742 | 161 | if ($force || !array_key_exists('oauth2', Yii::$app->i18n->translations)) { |
|||||
743 | 161 | Yii::$app->i18n->translations['oauth2'] = [ |
|||||
744 | 161 | 'class' => PhpMessageSource::class, |
|||||
745 | 161 | 'sourceLanguage' => 'en-US', |
|||||
746 | 161 | 'basePath' => __DIR__ . DIRECTORY_SEPARATOR . 'messages', |
|||||
747 | 161 | 'fileMap' => [ |
|||||
748 | 161 | 'oauth2' => 'oauth2.php', |
|||||
749 | 161 | ], |
|||||
750 | 161 | ]; |
|||||
751 | } |
||||||
752 | } |
||||||
753 | |||||||
754 | /** |
||||||
755 | * @param string $identifier The client identifier |
||||||
756 | * @param string $name The (user-friendly) name of the client |
||||||
757 | * @param int $grantTypes The grant types enabled for this client. |
||||||
758 | * Use bitwise `OR` to combine multiple types, |
||||||
759 | * e.g. `Oauth2Module::GRANT_TYPE_AUTH_CODE | Oauth2Module::GRANT_TYPE_REFRESH_TOKEN` |
||||||
760 | * @param string|string[] $redirectURIs One or multiple redirect URIs for the client |
||||||
761 | * @param int $type The client type (e.g. Confidential or Public) |
||||||
762 | * See `\rhertogh\Yii2Oauth2Server\interfaces\models\Oauth2ClientInterface::TYPES` for possible values |
||||||
763 | * @param string|null $secret The client secret in case the client `type` is `confidential`. |
||||||
764 | * @param string|string[]|array[]|Oauth2ScopeInterface[]|null $scopes |
||||||
765 | * @param int|null $userId |
||||||
766 | * @return Oauth2ClientInterface |
||||||
767 | * @throws InvalidConfigException |
||||||
768 | * @throws \yii\db\Exception |
||||||
769 | */ |
||||||
770 | 5 | public function createClient( |
|||||
771 | $identifier, |
||||||
772 | $name, |
||||||
773 | $grantTypes, |
||||||
774 | $redirectURIs, |
||||||
775 | $type, |
||||||
776 | $secret = null, |
||||||
777 | $scopes = null, |
||||||
778 | $userId = null, |
||||||
779 | $endUsersMayAuthorizeClient = null, |
||||||
780 | $skipAuthorizationIfScopeIsAllowed = null |
||||||
781 | ) { |
||||||
782 | 5 | if (!($this->serverRole & static::SERVER_ROLE_AUTHORIZATION_SERVER)) { |
|||||
783 | 1 | throw new InvalidCallException('Oauth2 server role does not include authorization server.'); |
|||||
784 | } |
||||||
785 | |||||||
786 | /** @var Oauth2ClientInterface $client */ |
||||||
787 | 4 | $client = Yii::createObject([ |
|||||
788 | 4 | 'class' => Oauth2ClientInterface::class, |
|||||
789 | 4 | 'identifier' => $identifier, |
|||||
790 | 4 | 'type' => $type, |
|||||
791 | 4 | 'name' => $name, |
|||||
792 | 4 | 'redirectUri' => $redirectURIs, |
|||||
793 | 4 | 'grantTypes' => $grantTypes, |
|||||
794 | 4 | 'endUsersMayAuthorizeClient' => $endUsersMayAuthorizeClient, |
|||||
795 | 4 | 'skip_authorization_if_scope_is_allowed' => $skipAuthorizationIfScopeIsAllowed, |
|||||
796 | 4 | 'clientCredentialsGrantUserId' => $userId |
|||||
797 | 4 | ]); |
|||||
798 | |||||||
799 | 4 | $transaction = $client::getDb()->beginTransaction(); |
|||||
800 | |||||||
801 | try { |
||||||
802 | 4 | if ($type == Oauth2ClientInterface::TYPE_CONFIDENTIAL) { |
|||||
803 | 4 | $client->setSecret($secret, $this->getCryptographer()); |
|||||
804 | } |
||||||
805 | |||||||
806 | 3 | $client |
|||||
807 | 3 | ->persist() |
|||||
808 | 3 | ->syncClientScopes($scopes, $this->getScopeRepository()); |
|||||
809 | |||||||
810 | 3 | $transaction->commit(); |
|||||
811 | 1 | } catch (\Exception $e) { |
|||||
812 | 1 | $transaction->rollBack(); |
|||||
813 | 1 | throw $e; |
|||||
814 | } |
||||||
815 | |||||||
816 | 3 | return $client; |
|||||
817 | } |
||||||
818 | |||||||
819 | /** |
||||||
820 | * @return CryptKey The private key of the server. |
||||||
821 | * @throws InvalidConfigException |
||||||
822 | * @since 1.0.0 |
||||||
823 | */ |
||||||
824 | 22 | public function getPrivateKey() |
|||||
825 | { |
||||||
826 | 22 | $privateKey = $this->privateKey; |
|||||
827 | 22 | if (StringHelper::startsWith($privateKey, '@')) { |
|||||
828 | 19 | $privateKey = 'file://' . Yii::getAlias($privateKey); |
|||||
0 ignored issues
–
show
Are you sure
Yii::getAlias($privateKey) of type false|string can be used in concatenation ?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
829 | } |
||||||
830 | 22 | return Yii::createObject(CryptKey::class, [$privateKey, $this->privateKeyPassphrase]); |
|||||
831 | } |
||||||
832 | |||||||
833 | /** |
||||||
834 | * @return CryptKey The public key of the server. |
||||||
835 | * @throws InvalidConfigException |
||||||
836 | * @since 1.0.0 |
||||||
837 | */ |
||||||
838 | 9 | public function getPublicKey() |
|||||
839 | { |
||||||
840 | 9 | $publicKey = $this->publicKey; |
|||||
841 | 9 | if (StringHelper::startsWith($publicKey, '@')) { |
|||||
842 | 6 | $publicKey = 'file://' . Yii::getAlias($publicKey); |
|||||
0 ignored issues
–
show
Are you sure
Yii::getAlias($publicKey) of type false|string can be used in concatenation ?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
843 | } |
||||||
844 | 9 | return Yii::createObject(CryptKey::class, [$publicKey]); |
|||||
845 | } |
||||||
846 | |||||||
847 | /** |
||||||
848 | * @return Oauth2AuthorizationServerInterface The authorization server. |
||||||
849 | * @throws InvalidConfigException |
||||||
850 | * @since 1.0.0 |
||||||
851 | */ |
||||||
852 | 27 | public function getAuthorizationServer() |
|||||
853 | { |
||||||
854 | 27 | if (!($this->serverRole & static::SERVER_ROLE_AUTHORIZATION_SERVER)) { |
|||||
855 | 1 | throw new InvalidCallException('Oauth2 server role does not include authorization server.'); |
|||||
856 | } |
||||||
857 | |||||||
858 | 26 | if (!$this->_authorizationServer) { |
|||||
859 | 26 | $this->ensureProperties(static::REQUIRED_SETTINGS_AUTHORIZATION_SERVER); |
|||||
860 | |||||||
861 | 21 | if (!$this->getCryptographer()->hasKey($this->defaultStorageEncryptionKey)) { |
|||||
862 | 1 | throw new InvalidConfigException( |
|||||
863 | 1 | 'Key "' . $this->defaultStorageEncryptionKey . '" is not set in $storageEncryptionKeys' |
|||||
864 | 1 | ); |
|||||
865 | } |
||||||
866 | |||||||
867 | /** @var Oauth2EncryptionKeyFactoryInterface $keyFactory */ |
||||||
868 | 19 | $keyFactory = Yii::createObject(Oauth2EncryptionKeyFactoryInterface::class); |
|||||
869 | try { |
||||||
870 | 19 | $codesEncryptionKey = $keyFactory->createFromAsciiSafeString($this->codesEncryptionKey); |
|||||
871 | 1 | } catch (BadFormatException $e) { |
|||||
872 | 1 | throw new InvalidConfigException( |
|||||
873 | 1 | '$codesEncryptionKey is malformed: ' . $e->getMessage(), |
|||||
874 | 1 | 0, |
|||||
875 | 1 | $e |
|||||
876 | 1 | ); |
|||||
877 | } catch (EnvironmentIsBrokenException $e) { |
||||||
878 | throw new InvalidConfigException( |
||||||
879 | 'Could not instantiate $codesEncryptionKey: ' . $e->getMessage(), |
||||||
880 | 0, |
||||||
881 | $e |
||||||
882 | ); |
||||||
883 | } |
||||||
884 | |||||||
885 | 18 | if ($this->enableOpenIdConnect) { |
|||||
886 | 18 | $responseTypeClass = Oauth2OidcBearerTokenResponseInterface::class; |
|||||
887 | } else { |
||||||
888 | $responseTypeClass = Oauth2BearerTokenResponseInterface::class; |
||||||
889 | } |
||||||
890 | 18 | $responseType = Yii::createObject($responseTypeClass, [ |
|||||
891 | 18 | $this, |
|||||
892 | 18 | ]); |
|||||
893 | |||||||
894 | 18 | $this->_authorizationServer = Yii::createObject(Oauth2AuthorizationServerInterface::class, [ |
|||||
895 | 18 | $this->getClientRepository(), |
|||||
896 | 18 | $this->getAccessTokenRepository(), |
|||||
897 | 18 | $this->getScopeRepository(), |
|||||
898 | 18 | $this->getPrivateKey(), |
|||||
899 | 18 | $codesEncryptionKey, |
|||||
900 | 18 | $responseType |
|||||
901 | 18 | ]); |
|||||
902 | |||||||
903 | 18 | if (!empty($this->grantTypes)) { |
|||||
904 | 18 | $grantTypes = $this->grantTypes; |
|||||
905 | |||||||
906 | 18 | if (is_callable($grantTypes)) { |
|||||
907 | 1 | call_user_func($grantTypes, $this->_authorizationServer, $this); |
|||||
0 ignored issues
–
show
It seems like
$grantTypes can also be of type League\OAuth2\Server\Grant\GrantTypeInterface and rhertogh\Yii2Oauth2Serve...antTypeFactoryInterface ; however, parameter $callback of call_user_func() does only seem to accept callable , 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
![]() |
|||||||
908 | } else { |
||||||
909 | 17 | if (!is_array($grantTypes)) { |
|||||
910 | 2 | $grantTypes = [$grantTypes]; |
|||||
911 | } |
||||||
912 | |||||||
913 | 17 | foreach ($grantTypes as $grantTypeDefinition) { |
|||||
914 | 17 | if ($grantTypeDefinition instanceof GrantTypeInterface) { |
|||||
915 | 1 | $accessTokenTTL = $this->getDefaultAccessTokenTTL(); |
|||||
916 | 1 | $this->_authorizationServer->enableGrantType($grantTypeDefinition, $accessTokenTTL); |
|||||
917 | } elseif ( |
||||||
918 | ( |
||||||
919 | 16 | is_numeric($grantTypeDefinition) |
|||||
920 | 16 | && array_key_exists($grantTypeDefinition, static::DEFAULT_GRANT_TYPE_FACTORIES) |
|||||
921 | ) |
||||||
922 | 16 | || is_a($grantTypeDefinition, Oauth2GrantTypeFactoryInterface::class, true) |
|||||
923 | ) { |
||||||
924 | if ( |
||||||
925 | 15 | is_numeric($grantTypeDefinition) |
|||||
926 | 15 | && array_key_exists($grantTypeDefinition, static::DEFAULT_GRANT_TYPE_FACTORIES) |
|||||
927 | ) { |
||||||
928 | 15 | $grantTypeDefinition = static::DEFAULT_GRANT_TYPE_FACTORIES[$grantTypeDefinition]; |
|||||
929 | } |
||||||
930 | |||||||
931 | /** @var Oauth2GrantTypeFactoryInterface $factory */ |
||||||
932 | 15 | $factory = Yii::createObject([ |
|||||
933 | 15 | 'class' => $grantTypeDefinition, |
|||||
934 | 15 | 'module' => $this, |
|||||
935 | 15 | ]); |
|||||
936 | 15 | $accessTokenTTL = $factory->getDefaultAccessTokenTTL() |
|||||
937 | 15 | ?? $this->getDefaultAccessTokenTTL(); |
|||||
938 | 15 | $this->_authorizationServer->enableGrantType($factory->getGrantType(), $accessTokenTTL); |
|||||
939 | } else { |
||||||
940 | 1 | throw new InvalidConfigException( |
|||||
941 | 1 | 'Unknown grantType ' |
|||||
942 | 1 | . ( |
|||||
943 | 1 | is_scalar($grantTypeDefinition) |
|||||
944 | 1 | ? '"' . $grantTypeDefinition . '".' |
|||||
945 | 1 | : 'with data type ' . gettype($grantTypeDefinition) |
|||||
946 | 1 | ) |
|||||
947 | 1 | ); |
|||||
948 | } |
||||||
949 | } |
||||||
950 | } |
||||||
951 | } |
||||||
952 | } |
||||||
953 | |||||||
954 | 17 | return $this->_authorizationServer; |
|||||
955 | } |
||||||
956 | |||||||
957 | /** |
||||||
958 | * @inheritDoc |
||||||
959 | * @throws InvalidConfigException |
||||||
960 | */ |
||||||
961 | 6 | public function getOidcScopeCollection() |
|||||
962 | { |
||||||
963 | 6 | if ($this->_oidcScopeCollection === null) { |
|||||
964 | 6 | $openIdConnectScopes = $this->getOpenIdConnectScopes(); |
|||||
965 | 6 | if ($openIdConnectScopes instanceof Oauth2OidcScopeCollectionInterface) { |
|||||
966 | 1 | $this->_oidcScopeCollection = $openIdConnectScopes; |
|||||
967 | 5 | } elseif (is_callable($openIdConnectScopes)) { |
|||||
968 | 1 | $this->_oidcScopeCollection = call_user_func($openIdConnectScopes, $this); |
|||||
969 | 1 | if (!($this->_oidcScopeCollection instanceof Oauth2OidcScopeCollectionInterface)) { |
|||||
970 | 1 | throw new InvalidConfigException( |
|||||
971 | 1 | '$openIdConnectScopes must return an instance of ' |
|||||
972 | 1 | . Oauth2OidcScopeCollectionInterface::class |
|||||
973 | 1 | ); |
|||||
974 | } |
||||||
975 | 4 | } elseif (is_array($openIdConnectScopes) || is_string($openIdConnectScopes)) { |
|||||
976 | 3 | $this->_oidcScopeCollection = Yii::createObject([ |
|||||
977 | 3 | 'class' => Oauth2OidcScopeCollectionInterface::class, |
|||||
978 | 3 | 'oidcScopes' => (array)$openIdConnectScopes, |
|||||
979 | 3 | ]); |
|||||
980 | } else { |
||||||
981 | 1 | throw new InvalidConfigException( |
|||||
982 | 1 | '$openIdConnectScopes must be a callable, array, string or ' |
|||||
983 | 1 | . Oauth2OidcScopeCollectionInterface::class |
|||||
984 | 1 | ); |
|||||
985 | } |
||||||
986 | } |
||||||
987 | |||||||
988 | 5 | return $this->_oidcScopeCollection; |
|||||
989 | } |
||||||
990 | |||||||
991 | /** |
||||||
992 | * @return Oauth2ResourceServerInterface The resource server. |
||||||
993 | * @throws InvalidConfigException |
||||||
994 | * @since 1.0.0 |
||||||
995 | */ |
||||||
996 | 7 | public function getResourceServer() |
|||||
997 | { |
||||||
998 | 7 | if (!($this->serverRole & static::SERVER_ROLE_RESOURCE_SERVER)) { |
|||||
999 | 1 | throw new InvalidCallException('Oauth2 server role does not include resource server.'); |
|||||
1000 | } |
||||||
1001 | |||||||
1002 | 6 | if (!$this->_resourceServer) { |
|||||
1003 | 6 | $this->ensureProperties(static::REQUIRED_SETTINGS_RESOURCE_SERVER); |
|||||
1004 | |||||||
1005 | 5 | $accessTokenRepository = $this->getAccessTokenRepository() |
|||||
1006 | 5 | ->setRevocationValidation($this->resourceServerAccessTokenRevocationValidation); |
|||||
1007 | |||||||
1008 | 5 | $this->_resourceServer = Yii::createObject(Oauth2ResourceServerInterface::class, [ |
|||||
1009 | 5 | $accessTokenRepository, |
|||||
1010 | 5 | $this->getPublicKey(), |
|||||
1011 | 5 | ]); |
|||||
1012 | } |
||||||
1013 | |||||||
1014 | 5 | return $this->_resourceServer; |
|||||
1015 | } |
||||||
1016 | |||||||
1017 | /** |
||||||
1018 | * @return Oauth2CryptographerInterface The data cryptographer for the module. |
||||||
1019 | * @throws InvalidConfigException |
||||||
1020 | * @since 1.0.0 |
||||||
1021 | */ |
||||||
1022 | 27 | public function getCryptographer() |
|||||
1023 | { |
||||||
1024 | 27 | if (!$this->_cryptographer) { |
|||||
1025 | 27 | $this->_cryptographer = Yii::createObject([ |
|||||
1026 | 27 | 'class' => Oauth2CryptographerInterface::class, |
|||||
1027 | 27 | 'keys' => $this->storageEncryptionKeys, |
|||||
1028 | 27 | 'defaultKeyName' => $this->defaultStorageEncryptionKey, |
|||||
1029 | 27 | ]); |
|||||
1030 | } |
||||||
1031 | |||||||
1032 | 26 | return $this->_cryptographer; |
|||||
1033 | } |
||||||
1034 | |||||||
1035 | /** |
||||||
1036 | * @param string|null $newKeyName |
||||||
1037 | * @return array |
||||||
1038 | * @throws InvalidConfigException |
||||||
1039 | */ |
||||||
1040 | 1 | public function rotateStorageEncryptionKeys($newKeyName = null) |
|||||
1041 | { |
||||||
1042 | 1 | $cryptographer = $this->getCryptographer(); |
|||||
1043 | |||||||
1044 | 1 | $result = []; |
|||||
1045 | 1 | foreach (static::ENCRYPTED_MODELS as $modelInterface) { |
|||||
1046 | 1 | $modelClass = DiHelper::getValidatedClassName($modelInterface); |
|||||
1047 | 1 | if (!is_a($modelClass, Oauth2EncryptedStorageInterface::class, true)) { |
|||||
1048 | throw new InvalidConfigException($modelInterface . ' must implement ' |
||||||
1049 | . Oauth2EncryptedStorageInterface::class); |
||||||
1050 | } |
||||||
1051 | 1 | $result[$modelClass] = $modelClass::rotateStorageEncryptionKeys($cryptographer, $newKeyName); |
|||||
1052 | } |
||||||
1053 | |||||||
1054 | 1 | return $result; |
|||||
1055 | } |
||||||
1056 | |||||||
1057 | /** |
||||||
1058 | * Checks if the connection is using TLS or if the remote IP address is allowed to connect without TLS. |
||||||
1059 | * @return bool |
||||||
1060 | */ |
||||||
1061 | 12 | public function validateTlsConnection() |
|||||
1062 | { |
||||||
1063 | 12 | if (Yii::$app->request->getIsSecureConnection()) { |
|||||
1064 | 1 | return true; |
|||||
1065 | } |
||||||
1066 | |||||||
1067 | if ( |
||||||
1068 | 11 | !empty($this->nonTlsAllowedRanges) |
|||||
1069 | 11 | && (new IpValidator(['ranges' => $this->nonTlsAllowedRanges]))->validate(Yii::$app->request->getRemoteIP()) |
|||||
1070 | ) { |
||||||
1071 | 7 | return true; |
|||||
1072 | } |
||||||
1073 | |||||||
1074 | 4 | return false; |
|||||
1075 | } |
||||||
1076 | |||||||
1077 | /** |
||||||
1078 | * @return array |
||||||
1079 | * @throws InvalidConfigException |
||||||
1080 | */ |
||||||
1081 | public function getStorageEncryptionKeyUsage() |
||||||
1082 | { |
||||||
1083 | $cryptographer = $this->getCryptographer(); |
||||||
1084 | |||||||
1085 | $result = []; |
||||||
1086 | foreach (static::ENCRYPTED_MODELS as $modelInterface) { |
||||||
1087 | $modelClass = DiHelper::getValidatedClassName($modelInterface); |
||||||
1088 | if (!is_a($modelClass, Oauth2EncryptedStorageInterface::class, true)) { |
||||||
1089 | throw new InvalidConfigException($modelInterface . ' must implement ' |
||||||
1090 | . Oauth2EncryptedStorageInterface::class); |
||||||
1091 | } |
||||||
1092 | |||||||
1093 | $result[$modelClass] = $modelClass::getUsedStorageEncryptionKeys($cryptographer); |
||||||
1094 | } |
||||||
1095 | |||||||
1096 | return $result; |
||||||
1097 | } |
||||||
1098 | |||||||
1099 | /** |
||||||
1100 | * @param Oauth2ClientInterface $client |
||||||
1101 | * @param string[] $requestedScopeIdentifiers |
||||||
1102 | * @throws Oauth2ServerException |
||||||
1103 | */ |
||||||
1104 | 6 | public function validateAuthRequestScopes($client, $requestedScopeIdentifiers, $redirectUri = null) |
|||||
1105 | { |
||||||
1106 | 6 | if (!$client->validateAuthRequestScopes($requestedScopeIdentifiers, $unknownScopes, $unauthorizedScopes)) { |
|||||
1107 | Yii::info('Invalid scope for client "' . $client->getIdentifier() . '": ' |
||||||
1108 | . VarDumper::export(['unauthorizedScopes' => $unauthorizedScopes, 'unknownScopes' => $unknownScopes])); |
||||||
1109 | |||||||
1110 | if ( |
||||||
1111 | $client->getExceptionOnInvalidScope() === true |
||||||
1112 | || ( |
||||||
1113 | $client->getExceptionOnInvalidScope() === null |
||||||
1114 | && $this->exceptionOnInvalidScope === true |
||||||
1115 | ) |
||||||
1116 | ) { |
||||||
1117 | if ($unknownScopes) { |
||||||
1118 | throw Oauth2ServerException::unknownScope(array_shift($unknownScopes), $redirectUri); |
||||||
1119 | } |
||||||
1120 | throw Oauth2ServerException::scopeNotAllowedForClient(array_shift($unauthorizedScopes), $redirectUri); |
||||||
1121 | } |
||||||
1122 | } |
||||||
1123 | } |
||||||
1124 | |||||||
1125 | /** |
||||||
1126 | * Generates a redirect Response to the Client Authorization page where the user is prompted to authorize the |
||||||
1127 | * Client and requested Scope. |
||||||
1128 | * @param Oauth2ClientAuthorizationRequestInterface $clientAuthorizationRequest |
||||||
1129 | * @return Response |
||||||
1130 | * @since 1.0.0 |
||||||
1131 | */ |
||||||
1132 | 5 | public function generateClientAuthReqRedirectResponse($clientAuthorizationRequest) |
|||||
1133 | { |
||||||
1134 | 5 | $this->setClientAuthReqSession($clientAuthorizationRequest); |
|||||
1135 | 5 | if (!empty($this->clientAuthorizationUrl)) { |
|||||
1136 | 1 | $url = $this->clientAuthorizationUrl; |
|||||
1137 | } else { |
||||||
1138 | 4 | $url = $this->uniqueId |
|||||
1139 | 4 | . '/' . Oauth2ConsentControllerInterface::CONTROLLER_NAME |
|||||
1140 | 4 | . '/' . Oauth2ConsentControllerInterface::ACTION_NAME_AUTHORIZE_CLIENT; |
|||||
1141 | } |
||||||
1142 | 5 | return Yii::$app->response->redirect([ |
|||||
1143 | 5 | $url, |
|||||
1144 | 5 | 'clientAuthorizationRequestId' => $clientAuthorizationRequest->getRequestId(), |
|||||
1145 | 5 | ]); |
|||||
1146 | } |
||||||
1147 | |||||||
1148 | /** |
||||||
1149 | * Generates a redirect Response to the End Session Authorization page where the user is prompted to authorize the |
||||||
1150 | * logout. |
||||||
1151 | * @param Oauth2EndSessionAuthorizationRequestInterface $endSessionAuthorizationRequest |
||||||
1152 | * @return Response |
||||||
1153 | * @since 1.0.0 |
||||||
1154 | */ |
||||||
1155 | public function generateEndSessionAuthReqRedirectResponse($endSessionAuthorizationRequest) |
||||||
1156 | { |
||||||
1157 | $this->setEndSessionAuthReqSession($endSessionAuthorizationRequest); |
||||||
1158 | if (!empty($this->openIdConnectLogoutConfirmationUrl)) { |
||||||
1159 | $url = $this->openIdConnectLogoutConfirmationUrl; |
||||||
1160 | } else { |
||||||
1161 | $url = $this->uniqueId |
||||||
1162 | . '/' . Oauth2ConsentControllerInterface::CONTROLLER_NAME |
||||||
1163 | . '/' . Oauth2ConsentControllerInterface::ACTION_NAME_AUTHORIZE_END_SESSION; |
||||||
1164 | } |
||||||
1165 | return Yii::$app->response->redirect([ |
||||||
1166 | $url, |
||||||
1167 | 'endSessionAuthorizationRequestId' => $endSessionAuthorizationRequest->getRequestId(), |
||||||
1168 | ]); |
||||||
1169 | } |
||||||
1170 | |||||||
1171 | /** |
||||||
1172 | * Get a previously stored Client Authorization Request from the session. |
||||||
1173 | * @param string $requestId |
||||||
1174 | * @return Oauth2ClientAuthorizationRequestInterface|null |
||||||
1175 | * @since 1.0.0 |
||||||
1176 | */ |
||||||
1177 | 5 | public function getClientAuthReqSession($requestId) |
|||||
1178 | { |
||||||
1179 | 5 | return $this->getAuthReqSession( |
|||||
1180 | 5 | $requestId, |
|||||
1181 | 5 | static::CLIENT_AUTHORIZATION_REQUEST_SESSION_PREFIX, |
|||||
1182 | 5 | Oauth2ClientAuthorizationRequestInterface::class, |
|||||
1183 | 5 | ); |
|||||
1184 | } |
||||||
1185 | |||||||
1186 | /** |
||||||
1187 | * Get a previously stored OIDC End Session Authorization Request from the session. |
||||||
1188 | * @param string $requestId |
||||||
1189 | * @return Oauth2EndSessionAuthorizationRequestInterface|null |
||||||
1190 | * @since 1.0.0 |
||||||
1191 | */ |
||||||
1192 | public function getEndSessionAuthReqSession($requestId) |
||||||
1193 | { |
||||||
1194 | return $this->getAuthReqSession( |
||||||
1195 | $requestId, |
||||||
1196 | static::END_SESSION_AUTHORIZATION_REQUEST_SESSION_PREFIX, |
||||||
1197 | Oauth2EndSessionAuthorizationRequestInterface::class, |
||||||
1198 | ); |
||||||
1199 | } |
||||||
1200 | |||||||
1201 | /** |
||||||
1202 | * Get a previously stored Authorization Request from the session. |
||||||
1203 | * @template T of Oauth2BaseAuthorizationRequestInterface |
||||||
1204 | * @param string $requestId |
||||||
1205 | * @param string $cachePrefix |
||||||
1206 | * @param class-string<T> $expectedInterface |
||||||
0 ignored issues
–
show
|
|||||||
1207 | * @return T|null |
||||||
1208 | * @since 1.0.0 |
||||||
1209 | */ |
||||||
1210 | 5 | protected function getAuthReqSession($requestId, $cachePrefix, $expectedInterface) |
|||||
1211 | { |
||||||
1212 | 5 | if (empty($requestId)) { |
|||||
1213 | return null; |
||||||
1214 | } |
||||||
1215 | 5 | $key = $cachePrefix . $requestId; |
|||||
1216 | 5 | $authorizationRequest = Yii::$app->session->get($key); |
|||||
0 ignored issues
–
show
The method
get() does not exist on null .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces. This is most likely a typographical error or the method has been renamed. ![]() |
|||||||
1217 | 5 | if (!($authorizationRequest instanceof $expectedInterface)) { |
|||||
1218 | 2 | if (!empty($authorizationRequest)) { |
|||||
1219 | 1 | Yii::warning( |
|||||
1220 | 1 | 'Found a Authorization Request Session with key "' . $key |
|||||
1221 | 1 | . '", but it\'s not a ' . $expectedInterface |
|||||
1222 | 1 | ); |
|||||
1223 | } |
||||||
1224 | 2 | return null; |
|||||
1225 | } |
||||||
1226 | 5 | if ($authorizationRequest->getRequestId() !== $requestId) { |
|||||
1227 | 1 | Yii::warning( |
|||||
1228 | 1 | 'Found a Authorization Request Session with key "' . $key |
|||||
1229 | 1 | . '", but its request id does not match "' . $requestId . '".' |
|||||
1230 | 1 | ); |
|||||
1231 | 1 | return null; |
|||||
1232 | } |
||||||
1233 | 5 | $authorizationRequest->setModule($this); |
|||||
1234 | |||||||
1235 | 5 | return $authorizationRequest; |
|||||
1236 | } |
||||||
1237 | |||||||
1238 | /** |
||||||
1239 | * Stores the Client Authorization Request in the session. |
||||||
1240 | * @param Oauth2ClientAuthorizationRequestInterface $clientAuthorizationRequest |
||||||
1241 | * @since 1.0.0 |
||||||
1242 | */ |
||||||
1243 | 8 | public function setClientAuthReqSession($clientAuthorizationRequest) |
|||||
1244 | { |
||||||
1245 | 8 | $this->setAuthReqSession( |
|||||
1246 | 8 | $clientAuthorizationRequest, |
|||||
1247 | 8 | static::CLIENT_AUTHORIZATION_REQUEST_SESSION_PREFIX |
|||||
1248 | 8 | ); |
|||||
1249 | } |
||||||
1250 | |||||||
1251 | /** |
||||||
1252 | * Stores the OIDC End Session Authorization Request in the session. |
||||||
1253 | * @param Oauth2EndSessionAuthorizationRequestInterface $endSessionAuthorizationRequest |
||||||
1254 | * @since 1.0.0 |
||||||
1255 | */ |
||||||
1256 | public function setEndSessionAuthReqSession($endSessionAuthorizationRequest) |
||||||
1257 | { |
||||||
1258 | $this->setAuthReqSession( |
||||||
1259 | $endSessionAuthorizationRequest, |
||||||
1260 | static::END_SESSION_AUTHORIZATION_REQUEST_SESSION_PREFIX |
||||||
1261 | ); |
||||||
1262 | } |
||||||
1263 | |||||||
1264 | /** |
||||||
1265 | * Stores the Authorization Request in the session. |
||||||
1266 | * @param Oauth2BaseAuthorizationRequestInterface $authorizationRequest |
||||||
1267 | * @param string $cachePrefix |
||||||
1268 | * @since 1.0.0 |
||||||
1269 | */ |
||||||
1270 | 8 | protected function setAuthReqSession($authorizationRequest, $cachePrefix) |
|||||
1271 | { |
||||||
1272 | 8 | $requestId = $authorizationRequest->getRequestId(); |
|||||
1273 | 8 | if (empty($requestId)) { |
|||||
1274 | 1 | throw new InvalidArgumentException('$authorizationRequest must return a request id.'); |
|||||
1275 | } |
||||||
1276 | 7 | $key = $cachePrefix . $requestId; |
|||||
1277 | 7 | Yii::$app->session->set($key, $authorizationRequest); |
|||||
1278 | } |
||||||
1279 | |||||||
1280 | /** |
||||||
1281 | * Clears a Client Authorization Request from the session storage. |
||||||
1282 | * @param string $requestId |
||||||
1283 | * @since 1.0.0 |
||||||
1284 | */ |
||||||
1285 | 2 | public function removeClientAuthReqSession($requestId) |
|||||
1286 | { |
||||||
1287 | 2 | $this->removeAuthReqSession($requestId, static::CLIENT_AUTHORIZATION_REQUEST_SESSION_PREFIX); |
|||||
1288 | } |
||||||
1289 | |||||||
1290 | /** |
||||||
1291 | * Clears an End Session Authorization Request from the session storage. |
||||||
1292 | * @param string $requestId |
||||||
1293 | * @since 1.0.0 |
||||||
1294 | */ |
||||||
1295 | public function removeEndSessionAuthReqSession($requestId) |
||||||
1296 | { |
||||||
1297 | $this->removeAuthReqSession($requestId, static::END_SESSION_AUTHORIZATION_REQUEST_SESSION_PREFIX); |
||||||
1298 | } |
||||||
1299 | |||||||
1300 | /** |
||||||
1301 | * Clears an Authorization Request from the session storage. |
||||||
1302 | * @param string $requestId |
||||||
1303 | * @param string $cachePrefix |
||||||
1304 | * @since 1.0.0 |
||||||
1305 | */ |
||||||
1306 | 2 | public function removeAuthReqSession($requestId, $cachePrefix) |
|||||
1307 | { |
||||||
1308 | 2 | if (empty($requestId)) { |
|||||
1309 | 1 | throw new InvalidArgumentException('$requestId can not be empty.'); |
|||||
1310 | } |
||||||
1311 | 1 | $key = $cachePrefix . $requestId; |
|||||
1312 | 1 | Yii::$app->session->remove($key); |
|||||
1313 | } |
||||||
1314 | |||||||
1315 | /** |
||||||
1316 | * Stores whether the user was authenticated during the completion of the Client Authorization Request. |
||||||
1317 | * @param string $clientAuthorizationRequestId |
||||||
1318 | * @param bool $authenticatedDuringRequest |
||||||
1319 | * @since 1.0.0 |
||||||
1320 | */ |
||||||
1321 | public function setUserAuthenticatedDuringClientAuthRequest( |
||||||
1322 | $clientAuthorizationRequestId, |
||||||
1323 | $authenticatedDuringRequest |
||||||
1324 | ) { |
||||||
1325 | $clientAuthorizationRequest = $this->getClientAuthReqSession($clientAuthorizationRequestId); |
||||||
1326 | if ($clientAuthorizationRequest) { |
||||||
1327 | $clientAuthorizationRequest->setUserAuthenticatedDuringRequest($authenticatedDuringRequest); |
||||||
1328 | $this->setClientAuthReqSession($clientAuthorizationRequest); |
||||||
1329 | } |
||||||
1330 | } |
||||||
1331 | |||||||
1332 | /** |
||||||
1333 | * Stores the user identity selected during the completion of the Client Authorization Request. |
||||||
1334 | * @param string $clientAuthorizationRequestId |
||||||
1335 | * @param Oauth2UserInterface $userIdentity |
||||||
1336 | * @since 1.0.0 |
||||||
1337 | */ |
||||||
1338 | public function setClientAuthRequestUserIdentity($clientAuthorizationRequestId, $userIdentity) |
||||||
1339 | { |
||||||
1340 | $clientAuthorizationRequest = $this->getClientAuthReqSession($clientAuthorizationRequestId); |
||||||
1341 | if ($clientAuthorizationRequest) { |
||||||
1342 | $clientAuthorizationRequest->setUserIdentity($userIdentity); |
||||||
1343 | $this->setClientAuthReqSession($clientAuthorizationRequest); |
||||||
1344 | } |
||||||
1345 | } |
||||||
1346 | |||||||
1347 | /** |
||||||
1348 | * Generates a redirect Response when the Client Authorization Request is completed. |
||||||
1349 | * @param Oauth2ClientAuthorizationRequestInterface $clientAuthorizationRequest |
||||||
1350 | * @return Response |
||||||
1351 | * @since 1.0.0 |
||||||
1352 | */ |
||||||
1353 | 1 | public function generateClientAuthReqCompledRedirectResponse($clientAuthorizationRequest) |
|||||
1354 | { |
||||||
1355 | 1 | $clientAuthorizationRequest->processAuthorization(); |
|||||
1356 | 1 | $this->setClientAuthReqSession($clientAuthorizationRequest); |
|||||
1357 | 1 | return Yii::$app->response->redirect($clientAuthorizationRequest->getAuthorizationRequestUrl()); |
|||||
1358 | } |
||||||
1359 | |||||||
1360 | /** |
||||||
1361 | * Generates a redirect Response when the End Session Authorization Request is completed. |
||||||
1362 | * @param Oauth2EndSessionAuthorizationRequestInterface $endSessionAuthorizationRequest |
||||||
1363 | * @return Response |
||||||
1364 | * @since 1.0.0 |
||||||
1365 | */ |
||||||
1366 | public function generateEndSessionAuthReqCompledRedirectResponse($endSessionAuthorizationRequest) |
||||||
1367 | { |
||||||
1368 | $endSessionAuthorizationRequest->processAuthorization(); |
||||||
1369 | $this->setEndSessionAuthReqSession($endSessionAuthorizationRequest); |
||||||
1370 | return Yii::$app->response->redirect($endSessionAuthorizationRequest->getEndSessionRequestUrl()); |
||||||
1371 | } |
||||||
1372 | |||||||
1373 | /** |
||||||
1374 | * @return IdentityInterface|Oauth2UserInterface|Oauth2OidcUserInterface|null |
||||||
1375 | * @throws InvalidConfigException |
||||||
1376 | * @since 1.0.0 |
||||||
1377 | */ |
||||||
1378 | 5 | public function getUserIdentity() |
|||||
1379 | { |
||||||
1380 | 5 | $user = Yii::$app->user->identity; |
|||||
1381 | 5 | if (!empty($user) && !($user instanceof Oauth2UserInterface)) { |
|||||
1382 | 1 | throw new InvalidConfigException( |
|||||
1383 | 1 | 'Yii::$app->user->identity (currently ' . get_class($user) |
|||||
1384 | 1 | . ') must implement ' . Oauth2UserInterface::class |
|||||
1385 | 1 | ); |
|||||
1386 | } |
||||||
1387 | 4 | return $user; |
|||||
1388 | } |
||||||
1389 | |||||||
1390 | /** |
||||||
1391 | * Validates a bearer token authenticated request. Note: this method does not return a result but will throw |
||||||
1392 | * an exception when the authentication fails. |
||||||
1393 | * @throws InvalidConfigException |
||||||
1394 | * @throws Oauth2ServerException |
||||||
1395 | * @since 1.0.0 |
||||||
1396 | */ |
||||||
1397 | 3 | public function validateAuthenticatedRequest() |
|||||
1398 | { |
||||||
1399 | 3 | $psr7Request = Psr7Helper::yiiToPsr7Request(Yii::$app->request); |
|||||
0 ignored issues
–
show
It seems like
Yii::app->request can also be of type yii\console\Request ; however, parameter $request of rhertogh\Yii2Oauth2Serve...per::yiiToPsr7Request() does only seem to accept yii\web\Request , 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
![]() |
|||||||
1400 | |||||||
1401 | 3 | $psr7Request = $this->getResourceServer()->validateAuthenticatedRequest($psr7Request); |
|||||
1402 | |||||||
1403 | 3 | $token = substr(Yii::$app->request->headers->get('Authorization'), self::BEARER_TOKEN_OFFSET); |
|||||
0 ignored issues
–
show
It seems like
Yii::app->request->headers->get('Authorization') can also be of type array and null ; however, parameter $string of substr() 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
![]() |
|||||||
1404 | |||||||
1405 | 3 | if ($token) { |
|||||
1406 | 3 | $claims = $this->getAccessToken($token)->claims(); |
|||||
1407 | |||||||
1408 | 3 | foreach ($claims->all() as $claimKey => $claimValue) { |
|||||
1409 | 3 | if (!$this->isDefaultClaimKey($claimKey)) { |
|||||
1410 | $psr7Request = $psr7Request->withAttribute($claimKey, $claimValue); |
||||||
1411 | } |
||||||
1412 | } |
||||||
1413 | } |
||||||
1414 | |||||||
1415 | 3 | $this->_oauthClaims = $psr7Request->getAttributes(); |
|||||
1416 | 3 | $this->_oauthClaimsAuthorizationHeader = Yii::$app->request->getHeaders()->get('Authorization'); |
|||||
0 ignored issues
–
show
It seems like
Yii::app->request->getHe...)->get('Authorization') can also be of type array . However, the property $_oauthClaimsAuthorizationHeader is declared as type null|string . Maybe add an additional type check?
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly. For example, imagine you have a variable Either this assignment is in error or a type check should be added for that assignment. class Id
{
public $id;
public function __construct($id)
{
$this->id = $id;
}
}
class Account
{
/** @var Id $id */
public $id;
}
$account_id = false;
if (starsAreRight()) {
$account_id = new Id(42);
}
$account = new Account();
if ($account instanceof Id)
{
$account->id = $account_id;
}
![]() |
|||||||
1417 | } |
||||||
1418 | |||||||
1419 | /** |
||||||
1420 | * Find a user identity bases on an access token. |
||||||
1421 | * Note: validateAuthenticatedRequest() must be called before this method is called. |
||||||
1422 | * @param string $token |
||||||
1423 | * @param string $type |
||||||
1424 | * @return Oauth2UserInterface|null |
||||||
1425 | * @throws InvalidConfigException |
||||||
1426 | * @throws Oauth2ServerException |
||||||
1427 | * @see validateAuthenticatedRequest() |
||||||
1428 | * @since 1.0.0 |
||||||
1429 | */ |
||||||
1430 | 4 | public function findIdentityByAccessToken($token, $type) |
|||||
1431 | { |
||||||
1432 | 4 | if (!is_a($type, Oauth2HttpBearerAuthInterface::class, true)) { |
|||||
1433 | 1 | throw new InvalidCallException($type . ' must implement ' . Oauth2HttpBearerAuthInterface::class); |
|||||
1434 | } |
||||||
1435 | |||||||
1436 | if ( |
||||||
1437 | 3 | !preg_match('/^Bearer\s+(.*?)$/', $this->_oauthClaimsAuthorizationHeader, $matches) |
|||||
0 ignored issues
–
show
It seems like
$this->_oauthClaimsAuthorizationHeader can also be of type null ; however, parameter $subject of preg_match() 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
![]() |
|||||||
1438 | 3 | || !Yii::$app->security->compareString($matches[1], $token) |
|||||
1439 | ) { |
||||||
1440 | 1 | throw new InvalidCallException( |
|||||
1441 | 1 | 'validateAuthenticatedRequest() must be called before findIdentityByAccessToken().' |
|||||
1442 | 1 | ); |
|||||
1443 | } |
||||||
1444 | |||||||
1445 | 2 | $userId = $this->getRequestOauthUserId(); |
|||||
1446 | 2 | if (empty($userId)) { |
|||||
1447 | 1 | return null; |
|||||
1448 | } |
||||||
1449 | |||||||
1450 | 1 | return $this->identityClass::findIdentity($userId); |
|||||
1451 | } |
||||||
1452 | |||||||
1453 | /** |
||||||
1454 | * Generate a "Personal Access Token" (PAT) which can be used as an alternative to using passwords |
||||||
1455 | * for authentication (e.g. when using an API or command line). |
||||||
1456 | * |
||||||
1457 | * Note: Personal Access Tokens are intended to access resources on behalf users themselves. |
||||||
1458 | * To grant access to resources on behalf of an organization, or for long-lived integrations, |
||||||
1459 | * you most likely want to define an Oauth2 Client with the "Client Credentials" grant |
||||||
1460 | * (https://oauth.net/2/grant-types/client-credentials). |
||||||
1461 | * |
||||||
1462 | * @param string $clientIdentifier The Oauth2 client identifier for which the PAT should be generated. |
||||||
1463 | * @param int|string $userIdentifier The identifier (primary key) of the user for which the PAT should be generated. |
||||||
1464 | * @param Oauth2ScopeInterface[]|string[]|string|null $scope The Access Token scope. |
||||||
1465 | * @param string|true|null $clientSecret If the client is a "confidential" client the secret is required. |
||||||
1466 | * If the boolean value `true` is passed, the client secret is automatically injected. |
||||||
1467 | * @return Oauth2AccessTokenData |
||||||
1468 | */ |
||||||
1469 | 3 | public function generatePersonalAccessToken($clientIdentifier, $userIdentifier, $scope = null, $clientSecret = null) |
|||||
1470 | { |
||||||
1471 | 3 | if (is_array($scope)) { |
|||||
1472 | 2 | $scopeIdentifiers = []; |
|||||
1473 | 2 | foreach ($scope as $scopeItem) { |
|||||
1474 | 2 | if (is_string($scopeItem)) { |
|||||
1475 | 1 | $scopeIdentifiers[] = $scopeItem; |
|||||
1476 | 1 | } elseif ($scopeItem instanceof Oauth2ScopeInterface) { |
|||||
1477 | 1 | $scopeIdentifiers[] = $scopeItem->getIdentifier(); |
|||||
1478 | } else { |
||||||
1479 | throw new InvalidArgumentException('If $scope is an array its elements must be either' |
||||||
1480 | . ' a string or an instance of ' . Oauth2ScopeInterface::class); |
||||||
1481 | } |
||||||
1482 | } |
||||||
1483 | 2 | $scope = implode(' ', $scopeIdentifiers); |
|||||
1484 | } |
||||||
1485 | |||||||
1486 | 3 | if ($clientSecret === true) { |
|||||
1487 | /** @var Oauth2ClientInterface $client */ |
||||||
1488 | 3 | $client = $this->getClientRepository()->findModelByIdentifier($clientIdentifier); |
|||||
1489 | 3 | if ($client && $client->isConfidential()) { |
|||||
1490 | 3 | $clientSecret = $client->getDecryptedSecret($this->getCryptographer()); |
|||||
1491 | } else { |
||||||
1492 | $clientSecret = null; |
||||||
1493 | } |
||||||
1494 | } |
||||||
1495 | |||||||
1496 | 3 | $request = (new Psr7ServerRequest('POST', ''))->withParsedBody([ |
|||||
1497 | 3 | 'grant_type' => static::GRANT_TYPE_IDENTIFIER_PERSONAL_ACCESS_TOKEN, |
|||||
1498 | 3 | 'client_id' => $clientIdentifier, |
|||||
1499 | 3 | 'client_secret' => $clientSecret, |
|||||
1500 | 3 | 'user_id' => $userIdentifier, |
|||||
1501 | 3 | 'scope' => $scope, |
|||||
1502 | 3 | ]); |
|||||
1503 | |||||||
1504 | 3 | return new Oauth2AccessTokenData(Json::decode( |
|||||
0 ignored issues
–
show
It seems like
yii\helpers\Json::decode...etBody()->__toString()) can also be of type null ; however, parameter $data of rhertogh\Yii2Oauth2Serve...okenData::__construct() does only seem to accept array , 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
![]() |
|||||||
1505 | 3 | $this->getAuthorizationServer() |
|||||
1506 | 3 | ->respondToAccessTokenRequest( |
|||||
1507 | 3 | $request, |
|||||
1508 | 3 | new Psr7Response() |
|||||
1509 | 3 | ) |
|||||
1510 | 3 | ->getBody() |
|||||
1511 | 3 | ->__toString() |
|||||
1512 | 3 | )); |
|||||
1513 | } |
||||||
1514 | |||||||
1515 | /** |
||||||
1516 | * @inheritDoc |
||||||
1517 | */ |
||||||
1518 | 5 | public function getRequestOauthClaim($attribute, $default = null) |
|||||
1519 | { |
||||||
1520 | 5 | if (empty($this->_oauthClaimsAuthorizationHeader)) { |
|||||
1521 | // User authorization was not processed by Oauth2Module. |
||||||
1522 | 1 | return $default; |
|||||
1523 | } |
||||||
1524 | 4 | if (Yii::$app->request->getHeaders()->get('Authorization') !== $this->_oauthClaimsAuthorizationHeader) { |
|||||
1525 | 1 | throw new InvalidCallException( |
|||||
1526 | 1 | 'App Request Authorization header does not match the processed Oauth header.' |
|||||
1527 | 1 | ); |
|||||
1528 | } |
||||||
1529 | 3 | return $this->_oauthClaims[$attribute] ?? $default; |
|||||
1530 | } |
||||||
1531 | |||||||
1532 | /** |
||||||
1533 | * Helper function to ensure the required properties are configured for the module. |
||||||
1534 | * @param string[] $properties |
||||||
1535 | * @throws InvalidConfigException |
||||||
1536 | * @since 1.0.0 |
||||||
1537 | */ |
||||||
1538 | 32 | protected function ensureProperties($properties) |
|||||
1539 | { |
||||||
1540 | 32 | foreach ($properties as $property) { |
|||||
1541 | 32 | if (empty($this->$property)) { |
|||||
1542 | 6 | throw new InvalidConfigException(__CLASS__ . '::$' . $property . ' must be set.'); |
|||||
1543 | } |
||||||
1544 | } |
||||||
1545 | } |
||||||
1546 | |||||||
1547 | /** |
||||||
1548 | * @throws InvalidConfigException |
||||||
1549 | */ |
||||||
1550 | public function logoutUser($revokeTokens = true) |
||||||
1551 | { |
||||||
1552 | $identity = $this->getUserIdentity(); |
||||||
0 ignored issues
–
show
Are you sure the assignment to
$identity is correct as $this->getUserIdentity() targeting rhertogh\Yii2Oauth2Serve...dule::getUserIdentity() seems to always return null.
This check looks for function or method calls that always return null and whose return value is assigned to a variable. class A
{
function getObject()
{
return null;
}
}
$a = new A();
$object = $a->getObject();
The method The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes. ![]() |
|||||||
1553 | |||||||
1554 | if ($identity) { |
||||||
0 ignored issues
–
show
|
|||||||
1555 | if ($revokeTokens) { |
||||||
1556 | $this->revokeTokensByUserId($identity->getId()); |
||||||
1557 | } |
||||||
1558 | |||||||
1559 | Yii::$app->user->logout(); |
||||||
1560 | } |
||||||
1561 | } |
||||||
1562 | |||||||
1563 | public function revokeTokensByUserId($userId) |
||||||
1564 | { |
||||||
1565 | $accessTokens = $this->getAccessTokenRepository()->revokeAccessTokensByUserId($userId); |
||||||
1566 | $accessTokenIds = array_map(fn($accessToken) => $accessToken->getPrimaryKey(), $accessTokens); |
||||||
1567 | $this->getRefreshTokenRepository()->revokeRefreshTokensByAccessTokenIds($accessTokenIds); |
||||||
1568 | } |
||||||
1569 | |||||||
1570 | 4 | public function getSupportedPromptValues() |
|||||
1571 | { |
||||||
1572 | 4 | $supportedPromptValues = [ |
|||||
1573 | 4 | Oauth2OidcAuthenticationRequestInterface::REQUEST_PARAMETER_PROMPT_NONE, |
|||||
1574 | 4 | Oauth2OidcAuthenticationRequestInterface::REQUEST_PARAMETER_PROMPT_LOGIN, |
|||||
1575 | 4 | Oauth2OidcAuthenticationRequestInterface::REQUEST_PARAMETER_PROMPT_CONSENT, |
|||||
1576 | 4 | Oauth2OidcAuthenticationRequestInterface::REQUEST_PARAMETER_PROMPT_SELECT_ACCOUNT, |
|||||
1577 | 4 | ]; |
|||||
1578 | |||||||
1579 | 4 | if (!empty($this->userAccountCreationUrl)) { |
|||||
1580 | 4 | $supportedPromptValues[] = Oauth2OidcAuthenticationRequestInterface::REQUEST_PARAMETER_PROMPT_CREATE; |
|||||
1581 | } |
||||||
1582 | |||||||
1583 | 4 | return $supportedPromptValues; |
|||||
1584 | } |
||||||
1585 | |||||||
1586 | /** |
||||||
1587 | * @return int |
||||||
1588 | */ |
||||||
1589 | 2 | public function getElaboratedHttpClientErrorsLogLevel() |
|||||
1590 | { |
||||||
1591 | 2 | if ($this->httpClientErrorsLogLevel === null) { |
|||||
1592 | 1 | return YII_DEBUG ? Logger::LEVEL_ERROR : Logger::LEVEL_INFO; |
|||||
1593 | } |
||||||
1594 | |||||||
1595 | 1 | return $this->httpClientErrorsLogLevel; |
|||||
1596 | } |
||||||
1597 | |||||||
1598 | |||||||
1599 | 3 | public function getJwtConfiguration(): Configuration |
|||||
1600 | { |
||||||
1601 | // Based on \League\OAuth2\Server\AuthorizationValidators\BearerTokenValidator::initJwtConfiguration(). |
||||||
1602 | 3 | $jwtConfiguration = Configuration::forSymmetricSigner( |
|||||
1603 | 3 | new Sha256(), |
|||||
1604 | 3 | InMemory::plainText('empty', 'empty') |
|||||
1605 | 3 | ); |
|||||
1606 | |||||||
1607 | 3 | $publicKey = $this->getPublicKey(); |
|||||
1608 | 3 | $jwtConfiguration->setValidationConstraints( |
|||||
1609 | 3 | new SignedWith( |
|||||
1610 | 3 | new Sha256(), |
|||||
1611 | 3 | InMemory::plainText($publicKey->getKeyContents(), $publicKey->getPassPhrase() ?? '') |
|||||
1612 | 3 | ) |
|||||
1613 | 3 | ); |
|||||
1614 | |||||||
1615 | 3 | return $jwtConfiguration; |
|||||
1616 | } |
||||||
1617 | |||||||
1618 | 3 | public function getAccessToken(string $token): Token |
|||||
1619 | { |
||||||
1620 | 3 | $jwtConfiguration = $this->getJwtConfiguration(); |
|||||
1621 | 3 | $accessToken = $jwtConfiguration->parser()->parse($token); |
|||||
1622 | 3 | $jwtConfiguration->validator()->assert($accessToken, ...$jwtConfiguration->validationConstraints()); |
|||||
1623 | 3 | Yii::debug('Found access token: ' . $token, __METHOD__); |
|||||
1624 | |||||||
1625 | 3 | return $accessToken; |
|||||
1626 | } |
||||||
1627 | |||||||
1628 | 3 | protected function isDefaultClaimKey(string $claimKey): bool |
|||||
1629 | { |
||||||
1630 | 3 | return in_array( |
|||||
1631 | 3 | $claimKey, |
|||||
1632 | 3 | [ |
|||||
1633 | 3 | 'aud', |
|||||
1634 | 3 | 'jti', |
|||||
1635 | 3 | 'iat', |
|||||
1636 | 3 | 'nbf', |
|||||
1637 | 3 | 'exp', |
|||||
1638 | 3 | 'sub', |
|||||
1639 | 3 | 'scopes', |
|||||
1640 | 3 | 'client_id', |
|||||
1641 | 3 | ] |
|||||
1642 | 3 | ); |
|||||
1643 | } |
||||||
1644 | } |
||||||
1645 |