From be7caa0d3bf416c306cef43e18ea10c05661fa70 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 22 Jan 2024 11:35:21 -0500 Subject: [PATCH 01/12] - adds permissions in workflow file in anticipation for token lockdown --- .github/workflows/conflicting-pr-label.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/conflicting-pr-label.yml b/.github/workflows/conflicting-pr-label.yml index da6e5f3..fb4a14e 100644 --- a/.github/workflows/conflicting-pr-label.yml +++ b/.github/workflows/conflicting-pr-label.yml @@ -11,6 +11,10 @@ on: types: [synchronize] branches: [ main ] +permissions: + pull-requests: write + contents: read + # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: # This workflow contains a single job called "build" From 73398e91f44d74ea479f09898426c4289cc32150 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 22 Jan 2024 14:18:51 -0500 Subject: [PATCH 02/12] - adds permissions to SQ workflow --- .github/workflows/pr-validation.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/pr-validation.yml b/.github/workflows/pr-validation.yml index 292d771..2ad69b1 100644 --- a/.github/workflows/pr-validation.yml +++ b/.github/workflows/pr-validation.yml @@ -7,6 +7,10 @@ on: pull_request: branches: [ main, dev ] +permissions: + contents: read + pull-requests: read + jobs: build: runs-on: ubuntu-latest From 39cc10ff04055f969b2cc62ba48ffedb76b2365c Mon Sep 17 00:00:00 2001 From: Philip Gichuhi Date: Fri, 16 Feb 2024 08:46:30 +0300 Subject: [PATCH 03/12] Expose cache used in access token provider --- src/PhpLeagueAccessTokenProvider.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/PhpLeagueAccessTokenProvider.php b/src/PhpLeagueAccessTokenProvider.php index 4d3993a..d570fd9 100644 --- a/src/PhpLeagueAccessTokenProvider.php +++ b/src/PhpLeagueAccessTokenProvider.php @@ -211,6 +211,16 @@ public function getOauthProvider(): AbstractProvider return $this->oauthProvider; } + /** + * Returns the underlying cache + * + * @return AccessTokenCache + */ + public function getAccessTokenCache(): AccessTokenCache + { + return $this->accessTokenCache; + } + /** * Attempts to cache the access token if the TokenRequestContext provides a cache key * @param AccessToken $token From 77e4a5606809af609edbb0a1d4673cef40d0bead Mon Sep 17 00:00:00 2001 From: Philip Gichuhi Date: Fri, 16 Feb 2024 14:30:06 +0300 Subject: [PATCH 04/12] Enable hydrating/initialising in-memory cache --- src/Cache/InMemoryAccessTokenCache.php | 66 ++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/src/Cache/InMemoryAccessTokenCache.php b/src/Cache/InMemoryAccessTokenCache.php index 0e94268..515b0fc 100644 --- a/src/Cache/InMemoryAccessTokenCache.php +++ b/src/Cache/InMemoryAccessTokenCache.php @@ -2,7 +2,9 @@ namespace Microsoft\Kiota\Authentication\Cache; +use InvalidArgumentException; use League\OAuth2\Client\Token\AccessToken; +use Microsoft\Kiota\Authentication\Oauth\TokenRequestContext; /** * Class InMemoryAccessTokenCache @@ -21,13 +23,77 @@ class InMemoryAccessTokenCache implements AccessTokenCache */ private array $accessTokens = []; + /** + * Initializes the InMemoryAccessTokenCache with an access token and its related context. To add more access tokens + * use withToken(). + * + * @param TokenRequestContext|null $tokenRequestContext + * @param AccessToken|null $accessToken + */ + public function __construct(?TokenRequestContext $tokenRequestContext = null, ?AccessToken $accessToken = null) + { + if ($tokenRequestContext && $accessToken) { + $tokenRequestContext->setCacheKey($accessToken); + if (!$tokenRequestContext->getCacheKey()) { + throw new InvalidArgumentException("Unable to initialize cache key for context using access token"); + } + + $this->accessTokens[$tokenRequestContext->getCacheKey()] = $accessToken; + return; + } + } + + /** + * Initializes the InMemoryAccessTokenCache with an access token and its related context. + * + * @param TokenRequestContext $tokenRequestContext + * @param AccessToken $accessToken + * @return self + * @throws InvalidArgumentException if the cache key cannot be initialized OR the cache already contains an access token with the same identity/TokenRequestContext + */ + public function withToken(TokenRequestContext $tokenRequestContext, AccessToken $accessToken): self + { + $tokenRequestContext->setCacheKey($accessToken); + if (!$tokenRequestContext->getCacheKey()) { + throw new InvalidArgumentException("Unable to initialize cache key for context using access token"); + } + if (array_key_exists($tokenRequestContext->getCacheKey(), $this->accessTokens)) { + throw new InvalidArgumentException("Cache already contains an access token with the same identity"); + } + $this->accessTokens[$tokenRequestContext->getCacheKey()] = $accessToken; + return $this; + } + + /** + * Returns the access token with the given identity from the cache + * + * @param string $identity + * @return AccessToken|null + */ public function getAccessToken(string $identity): ?AccessToken { return $this->accessTokens[$identity] ?? null; } + /** + * Adds an access token with the given identity to the cache + * + * @param string $identity + * @param AccessToken $accessToken + * @return void + */ public function persistAccessToken(string $identity, AccessToken $accessToken): void { $this->accessTokens[$identity] = $accessToken; } + + /** + * Returns the access token given the token request context + * + * @param TokenRequestContext $tokenRequestContext + * @return AccessToken|null + */ + public function getTokenWithContext(TokenRequestContext $tokenRequestContext): ?AccessToken { + return $this->getAccessToken($tokenRequestContext->getCacheKey()); + } } From 4740ba6d745f5d9a396e631968749aef59a1bda3 Mon Sep 17 00:00:00 2001 From: Philip Gichuhi Date: Mon, 19 Feb 2024 09:32:29 +0300 Subject: [PATCH 05/12] Add InMemoryAccessTokenCache tests --- src/Cache/InMemoryAccessTokenCache.php | 4 ++ tests/Cache/InMemoryAccessTokenCacheTest.php | 61 ++++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 tests/Cache/InMemoryAccessTokenCacheTest.php diff --git a/src/Cache/InMemoryAccessTokenCache.php b/src/Cache/InMemoryAccessTokenCache.php index 515b0fc..97da32b 100644 --- a/src/Cache/InMemoryAccessTokenCache.php +++ b/src/Cache/InMemoryAccessTokenCache.php @@ -92,8 +92,12 @@ public function persistAccessToken(string $identity, AccessToken $accessToken): * * @param TokenRequestContext $tokenRequestContext * @return AccessToken|null + * @throws InvalidArgumentException if $tokenRequestContext has a null cache key */ public function getTokenWithContext(TokenRequestContext $tokenRequestContext): ?AccessToken { + if (is_null($tokenRequestContext->getCacheKey())) { + throw new InvalidArgumentException("Unable to get token using context with a null cache key"); + } return $this->getAccessToken($tokenRequestContext->getCacheKey()); } } diff --git a/tests/Cache/InMemoryAccessTokenCacheTest.php b/tests/Cache/InMemoryAccessTokenCacheTest.php new file mode 100644 index 0000000..3e1b127 --- /dev/null +++ b/tests/Cache/InMemoryAccessTokenCacheTest.php @@ -0,0 +1,61 @@ +testTokenRequestContext = new ClientCredentialContext("tenantId", "clientId", "clientSecret"); + } + + public function testConstructorWorksWithEmptyArguments() { + $cache = new InMemoryAccessTokenCache(); + $this->assertInstanceOf(InMemoryAccessTokenCache::class, $cache); + } + + public function testConstructorInitialisesCache() { + $cache = new InMemoryAccessTokenCache($this->testTokenRequestContext, $this->createMock(AccessToken::class)); + $this->assertInstanceOf(AccessToken::class, $cache->getTokenWithContext($this->testTokenRequestContext)); + } + + public function tesWithTokenInitialisesCache() { + $cache = new InMemoryAccessTokenCache(); + $cache->withToken($this->testTokenRequestContext, $this->createMock(AccessToken::class)); + $this->assertInstanceOf(AccessToken::class, $cache->getTokenWithContext($this->testTokenRequestContext)); + } + + public function testWithTokenThrowsExceptionIfCacheKeyCannotBeInitialised() { + $tokenRequestContext = $this->createMock(TokenRequestContext::class); + $tokenRequestContext->method('getCacheKey')->willReturn(null); + $cache = new InMemoryAccessTokenCache(); + $this->expectException(\InvalidArgumentException::class); + $cache->withToken($tokenRequestContext, $this->createMock(AccessToken::class)); + } + + public function testWithTokenThrowsExceptionIfTokenRequestContextAlreadyExists() { + $cache = new InMemoryAccessTokenCache($this->testTokenRequestContext, $this->createMock(AccessToken::class)); + $this->expectException(\InvalidArgumentException::class); + $cache->withToken($this->testTokenRequestContext, $this->createMock(AccessToken::class)); + } + + public function testWithTokenAddsMultipleTokensToCache() { + $secondContext = $this->createMock(TokenRequestContext::class); + $secondContext->method('getCacheKey')->willReturn('second-key'); + + $cache = (new InMemoryAccessTokenCache()) + ->withToken($this->testTokenRequestContext, $this->createMock(AccessToken::class)) + ->withToken($secondContext, $this->createMock(AccessToken::class)); + + $this->assertInstanceOf(AccessToken::class, $cache->getTokenWithContext($this->testTokenRequestContext)); + $this->assertInstanceOf(AccessToken::class, $cache->getTokenWithContext($secondContext)); + } +} From f4426c57c9ee47654c11466870b86bdfd59be49f Mon Sep 17 00:00:00 2001 From: Philip Gichuhi Date: Mon, 19 Feb 2024 10:46:22 +0300 Subject: [PATCH 06/12] Update CHANGELOG and bump version in constants --- CHANGELOG.md | 6 ++++++ README.md | 2 +- src/Constants.php | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c17511..902ba91 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +## [1.1.0] + +### Added +- Enables initialising the `InMemoryAccessTokenCache` with tokens for re-use by the auth provider +- Exposes the access token cache used in the `PhpLeagueAccessTokenProvider` using `getAccessTokenCache()` + ## [1.0.2] ### Changed diff --git a/README.md b/README.md index c33424b..981110d 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ run `composer require microsoft/kiota-authentication-phpleague` or add the follo ```Shell { "require": { - "microsoft/kiota-authentication-phpleague": "^1.0.1" + "microsoft/kiota-authentication-phpleague": "^1.1.0" } } ``` diff --git a/src/Constants.php b/src/Constants.php index 5fc7480..4709496 100644 --- a/src/Constants.php +++ b/src/Constants.php @@ -4,5 +4,5 @@ class Constants { - public const VERSION = "1.0.2"; + public const VERSION = "1.1.0"; } From c9340276861f14fb17902079878906bd57f4d0c2 Mon Sep 17 00:00:00 2001 From: Philip Gichuhi Date: Mon, 19 Feb 2024 10:54:39 +0300 Subject: [PATCH 07/12] Update tests to use InMemoryCache methods --- tests/PhpLeagueAccessTokenProviderTest.php | 13 ++++++------ tests/Stub/StubAccessTokenCache.php | 24 ---------------------- 2 files changed, 7 insertions(+), 30 deletions(-) delete mode 100644 tests/Stub/StubAccessTokenCache.php diff --git a/tests/PhpLeagueAccessTokenProviderTest.php b/tests/PhpLeagueAccessTokenProviderTest.php index 436bfa1..7cdd8b5 100644 --- a/tests/PhpLeagueAccessTokenProviderTest.php +++ b/tests/PhpLeagueAccessTokenProviderTest.php @@ -10,6 +10,7 @@ use Http\Promise\FulfilledPromise; use InvalidArgumentException; use League\OAuth2\Client\Token\AccessToken; +use Microsoft\Kiota\Authentication\Cache\InMemoryAccessTokenCache; use Microsoft\Kiota\Authentication\Oauth\AuthorizationCodeCertificateContext; use Microsoft\Kiota\Authentication\Oauth\AuthorizationCodeContext; use Microsoft\Kiota\Authentication\Oauth\ClientCredentialCertificateContext; @@ -100,11 +101,10 @@ public function testGetAuthorizationTokenUsesCachedToken(): void $oauthContexts = $this->getOauthContexts(); /** @var TokenRequestContext $tokenRequestContext */ foreach ($oauthContexts as $tokenRequestContext) { - $tokenProvider = new PhpLeagueAccessTokenProvider($tokenRequestContext, [], [], null, $stubTokenCache = new StubAccessTokenCache()); - $tokenRequestContext->setCacheKey(new AccessToken(['access_token' => $this->testJWT])); - $stubTokenCache->accessTokens[$tokenRequestContext->getCacheKey()] = new AccessToken(['access_token' => $this->testJWT, 'expires' => time() + 5]); + $cache = new InMemoryAccessTokenCache($tokenRequestContext, new AccessToken(['access_token' => $this->testJWT, 'expires' => time() + 5])); + $tokenProvider = new PhpLeagueAccessTokenProvider($tokenRequestContext, [], [], null, $cache); $mockResponses = [ - new Response(200, [], json_encode(['access_token' => 'abc', 'expires_in' => 5])), + new Response(400), ]; $tokenProvider->getOauthProvider()->setHttpClient($this->getMockHttpClient($mockResponses)); $this->assertEquals($this->testJWT, $tokenProvider->getAuthorizationTokenAsync('https://graph.microsoft.com')->wait()); @@ -116,13 +116,14 @@ public function testNewAccessTokenIsUpdatedToTheCache(): void $oauthContexts = $this->getOauthContexts(); /** @var TokenRequestContext $tokenRequestContext */ foreach ($oauthContexts as $tokenRequestContext) { - $tokenProvider = new PhpLeagueAccessTokenProvider($tokenRequestContext, [], [], null, $stubTokenCache = new StubAccessTokenCache()); + $cache = new InMemoryAccessTokenCache(); + $tokenProvider = new PhpLeagueAccessTokenProvider($tokenRequestContext, [], [], null, $cache); $mockResponses = [ new Response(200, [], json_encode(['access_token' => $this->testJWT, 'expires_in' => 5])), ]; $tokenProvider->getOauthProvider()->setHttpClient($this->getMockHttpClient($mockResponses)); $this->assertEquals($this->testJWT, $tokenProvider->getAuthorizationTokenAsync('https://graph.microsoft.com')->wait()); - $this->assertEquals($this->testJWT, $stubTokenCache->accessTokens[$tokenRequestContext->getCacheKey()]->getToken()); + $this->assertEquals($this->testJWT, $cache->getTokenWithContext($tokenRequestContext)); } } diff --git a/tests/Stub/StubAccessTokenCache.php b/tests/Stub/StubAccessTokenCache.php deleted file mode 100644 index 5c046b9..0000000 --- a/tests/Stub/StubAccessTokenCache.php +++ /dev/null @@ -1,24 +0,0 @@ - - */ - public array $accessTokens = []; - - public function getAccessToken(string $identity): ?AccessToken - { - return $this->accessTokens[$identity] ?? null; - } - - public function persistAccessToken(string $identity, AccessToken $accessToken): void - { - $this->accessTokens[$identity] = $accessToken; - } -} From c9a8cf76eb115fb02e92fced3b8e75ff1f89032e Mon Sep 17 00:00:00 2001 From: Philip Gichuhi Date: Mon, 19 Feb 2024 11:08:01 +0300 Subject: [PATCH 08/12] Fix SonarCloud issues --- src/Cache/InMemoryAccessTokenCache.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Cache/InMemoryAccessTokenCache.php b/src/Cache/InMemoryAccessTokenCache.php index 97da32b..e5f1190 100644 --- a/src/Cache/InMemoryAccessTokenCache.php +++ b/src/Cache/InMemoryAccessTokenCache.php @@ -39,7 +39,6 @@ public function __construct(?TokenRequestContext $tokenRequestContext = null, ?A } $this->accessTokens[$tokenRequestContext->getCacheKey()] = $accessToken; - return; } } @@ -49,7 +48,8 @@ public function __construct(?TokenRequestContext $tokenRequestContext = null, ?A * @param TokenRequestContext $tokenRequestContext * @param AccessToken $accessToken * @return self - * @throws InvalidArgumentException if the cache key cannot be initialized OR the cache already contains an access token with the same identity/TokenRequestContext + * @throws InvalidArgumentException if the cache key cannot be initialized + * OR the cache already contains an access token with the same identity/TokenRequestContext */ public function withToken(TokenRequestContext $tokenRequestContext, AccessToken $accessToken): self { From f8028d6d8f9bc2b728b91c93a83eddf4c58eb49d Mon Sep 17 00:00:00 2001 From: Philip Gichuhi Date: Tue, 20 Feb 2024 16:05:31 +0300 Subject: [PATCH 09/12] Provide method to initialise authentication provider with custom access token provider implementation --- src/PhpLeagueAccessTokenProvider.php | 24 ++++++++++++++++++++++++ src/PhpLeagueAuthenticationProvider.php | 13 +++++++++++++ 2 files changed, 37 insertions(+) diff --git a/src/PhpLeagueAccessTokenProvider.php b/src/PhpLeagueAccessTokenProvider.php index d570fd9..6d8f9f9 100644 --- a/src/PhpLeagueAccessTokenProvider.php +++ b/src/PhpLeagueAccessTokenProvider.php @@ -221,6 +221,30 @@ public function getAccessTokenCache(): AccessTokenCache return $this->accessTokenCache; } + /** + * @return TokenRequestContext + */ + public function getTokenRequestContext(): TokenRequestContext + { + return $this->tokenRequestContext; + } + + /** + * @return array + */ + public function getScopes(): array + { + return $this->scopes; + } + + /** + * @return array + */ + public function getAllowedHosts(): array + { + return $this->allowedHostsValidator->getAllowedHosts(); + } + /** * Attempts to cache the access token if the TokenRequestContext provides a cache key * @param AccessToken $token diff --git a/src/PhpLeagueAuthenticationProvider.php b/src/PhpLeagueAuthenticationProvider.php index 3075788..1bd419e 100644 --- a/src/PhpLeagueAuthenticationProvider.php +++ b/src/PhpLeagueAuthenticationProvider.php @@ -45,4 +45,17 @@ public function getAccessTokenProvider(): PhpLeagueAccessTokenProvider return $this->accessTokenProvider; } + /** + * Get an instance of PhpLeagueAuthenticationProvider your custom PhpLeagueAccessTokenProvider + * + * @param PhpLeagueAccessTokenProvider $phpLeagueAccessTokenProvider + * @return self + */ + public static function createWithAccessTokenProvider(PhpLeagueAccessTokenProvider $phpLeagueAccessTokenProvider): self + { + $authProvider = new PhpLeagueAuthenticationProvider($phpLeagueAccessTokenProvider->getTokenRequestContext(), $phpLeagueAccessTokenProvider->getScopes(), $phpLeagueAccessTokenProvider->getAllowedHosts()); + $authProvider->accessTokenProvider = $phpLeagueAccessTokenProvider; + return $authProvider; + } + } From 0db201488fbe7a59e0746c671660af8e2d748a3e Mon Sep 17 00:00:00 2001 From: Philip Gichuhi Date: Fri, 23 Feb 2024 10:49:55 +0300 Subject: [PATCH 10/12] Refactor in-memory cache constructor --- src/Cache/InMemoryAccessTokenCache.php | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/Cache/InMemoryAccessTokenCache.php b/src/Cache/InMemoryAccessTokenCache.php index e5f1190..c427ab9 100644 --- a/src/Cache/InMemoryAccessTokenCache.php +++ b/src/Cache/InMemoryAccessTokenCache.php @@ -33,12 +33,7 @@ class InMemoryAccessTokenCache implements AccessTokenCache public function __construct(?TokenRequestContext $tokenRequestContext = null, ?AccessToken $accessToken = null) { if ($tokenRequestContext && $accessToken) { - $tokenRequestContext->setCacheKey($accessToken); - if (!$tokenRequestContext->getCacheKey()) { - throw new InvalidArgumentException("Unable to initialize cache key for context using access token"); - } - - $this->accessTokens[$tokenRequestContext->getCacheKey()] = $accessToken; + $this->withToken($tokenRequestContext, $accessToken); } } From 007acf3aa6d41a846e16146460898bdb0511b5f8 Mon Sep 17 00:00:00 2001 From: Philip Gichuhi Date: Fri, 23 Feb 2024 11:03:58 +0300 Subject: [PATCH 11/12] Increase test coverage --- tests/PhpLeagueAuthenticationProviderTest.php | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/PhpLeagueAuthenticationProviderTest.php b/tests/PhpLeagueAuthenticationProviderTest.php index 1858b9f..ab2c132 100644 --- a/tests/PhpLeagueAuthenticationProviderTest.php +++ b/tests/PhpLeagueAuthenticationProviderTest.php @@ -3,6 +3,7 @@ namespace Microsoft\Kiota\Authentication\Test; use Microsoft\Kiota\Authentication\Oauth\ClientCredentialContext; +use Microsoft\Kiota\Authentication\PhpLeagueAccessTokenProvider; use Microsoft\Kiota\Authentication\PhpLeagueAuthenticationProvider; use PHPUnit\Framework\TestCase; @@ -23,4 +24,23 @@ public function testCorrectOauthProviderEndpointsExposed(): void $expected = "https://login.microsoftonline.com/tenantId/oauth2/v2.0/authorize"; $this->assertEquals($expected, $this->defaultAuthProvider->getAccessTokenProvider()->getOauthProvider()->getBaseAuthorizationUrl()); } + + public function testCreateWithAccessTokenProvider(): void + { + $context = new ClientCredentialContext('tenantId', 'clientId', 'secret'); + $scopes = ['https://graph.microsoft.com/.default']; + $allowedHosts = []; + $authenticationProvider = PhpLeagueAuthenticationProvider::createWithAccessTokenProvider( + new PhpLeagueAccessTokenProvider( + $context, + $scopes, + $allowedHosts + ) + ); + $this->assertInstanceOf(PhpLeagueAuthenticationProvider::class, $authenticationProvider); + $this->assertInstanceOf(PhpLeagueAccessTokenProvider::class, $authenticationProvider->getAccessTokenProvider()); + $this->assertEquals($context, $authenticationProvider->getAccessTokenProvider()->getTokenRequestContext()); + $this->assertEquals($scopes, $authenticationProvider->getAccessTokenProvider()->getScopes()); + $this->assertEquals($allowedHosts, $authenticationProvider->getAccessTokenProvider()->getAllowedHosts()); + } } From 36efdac1d47ada43b06cf594a72adebf390ff656 Mon Sep 17 00:00:00 2001 From: Philip Gichuhi Date: Fri, 23 Feb 2024 11:07:00 +0300 Subject: [PATCH 12/12] Fix SonarCloud quality issues --- src/PhpLeagueAuthenticationProvider.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/PhpLeagueAuthenticationProvider.php b/src/PhpLeagueAuthenticationProvider.php index 1bd419e..bf1640b 100644 --- a/src/PhpLeagueAuthenticationProvider.php +++ b/src/PhpLeagueAuthenticationProvider.php @@ -51,9 +51,15 @@ public function getAccessTokenProvider(): PhpLeagueAccessTokenProvider * @param PhpLeagueAccessTokenProvider $phpLeagueAccessTokenProvider * @return self */ - public static function createWithAccessTokenProvider(PhpLeagueAccessTokenProvider $phpLeagueAccessTokenProvider): self + public static function createWithAccessTokenProvider( + PhpLeagueAccessTokenProvider $phpLeagueAccessTokenProvider + ): self { - $authProvider = new PhpLeagueAuthenticationProvider($phpLeagueAccessTokenProvider->getTokenRequestContext(), $phpLeagueAccessTokenProvider->getScopes(), $phpLeagueAccessTokenProvider->getAllowedHosts()); + $authProvider = new PhpLeagueAuthenticationProvider( + $phpLeagueAccessTokenProvider->getTokenRequestContext(), + $phpLeagueAccessTokenProvider->getScopes(), + $phpLeagueAccessTokenProvider->getAllowedHosts() + ); $authProvider->accessTokenProvider = $phpLeagueAccessTokenProvider; return $authProvider; }