From 82551bc60e3ef2cc11118366708b0bca05c1f958 Mon Sep 17 00:00:00 2001 From: Philip Gichuhi Date: Fri, 8 Nov 2024 12:00:07 +0200 Subject: [PATCH] feat: Use hash of the access token as cache key for all delegated permissions access tokens --- src/Oauth/ApplicationPermissionTrait.php | 4 ++-- src/Oauth/DelegatedPermissionTrait.php | 15 ++++----------- src/Oauth/TokenRequestContext.php | 4 ++-- tests/Cache/InMemoryAccessTokenCacheTest.php | 12 ++++++++++++ 4 files changed, 20 insertions(+), 15 deletions(-) diff --git a/src/Oauth/ApplicationPermissionTrait.php b/src/Oauth/ApplicationPermissionTrait.php index dc57609..e077e9e 100644 --- a/src/Oauth/ApplicationPermissionTrait.php +++ b/src/Oauth/ApplicationPermissionTrait.php @@ -32,7 +32,7 @@ abstract public function getTenantId(): string; /** * Set the identity of the user/application. This is used as the unique cache key - * For delegated permissions the key is {tenantId}-{clientId}-{userId} + * For delegated permissions the key is {tenantId}-{clientId}-{accessTokenHash} * For application permissions, they key is {tenantId}-{clientId} * @param AccessToken|null $accessToken * @return void @@ -44,7 +44,7 @@ public function setCacheKey(?AccessToken $accessToken = null): void /** * Return the identity of the user/application. This is used as the unique cache key - * For delegated permissions the key is {tenantId}-{clientId}-{userId} + * For delegated permissions the key is {tenantId}-{clientId}-{accessTokenHash} * For application permissions, they key is {tenantId}-{clientId} * @return string|null */ diff --git a/src/Oauth/DelegatedPermissionTrait.php b/src/Oauth/DelegatedPermissionTrait.php index 413dd84..abc89e5 100644 --- a/src/Oauth/DelegatedPermissionTrait.php +++ b/src/Oauth/DelegatedPermissionTrait.php @@ -11,7 +11,6 @@ use League\OAuth2\Client\Token\AccessToken; - trait DelegatedPermissionTrait { use CAEConfigurationTrait; @@ -33,7 +32,7 @@ abstract public function getTenantId(): string; /** * Set the identity of the user/application. This is used as the unique cache key - * For delegated permissions the key is {tenantId}-{clientId}-{userId} + * For delegated permissions the key is {tenantId}-{clientId}-{accessTokenHash} * For application permissions, they key is {tenantId}-{clientId} * @param AccessToken|null $accessToken * @return void @@ -41,20 +40,14 @@ abstract public function getTenantId(): string; public function setCacheKey(?AccessToken $accessToken = null): void { if ($accessToken && $accessToken->getToken()) { - $tokenParts = explode('.', $accessToken->getToken()); - if (count($tokenParts) == 3) { - $payload = json_decode(base64_decode($tokenParts[1]), true); - if (is_array($payload) && array_key_exists('sub', $payload)) { - $subject = $payload['sub']; - $this->cacheKey = ($subject) ? "{$this->getTenantId()}-{$this->getClientId()}-{$subject}" : null; - } - } + $uniqueIdentifier = password_hash($accessToken->getToken(), PASSWORD_DEFAULT); + $this->cacheKey = "{$this->getTenantId()}-{$this->getClientId()}-{$uniqueIdentifier}"; } } /** * Return the identity of the user/application. This is used as the unique cache key - * For delegated permissions the key is {tenantId}-{clientId}-{userId} + * For delegated permissions the key is {tenantId}-{clientId}-{accessTokenHash} * For application permissions, they key is {tenantId}-{clientId} * @return string|null */ diff --git a/src/Oauth/TokenRequestContext.php b/src/Oauth/TokenRequestContext.php index 77c0cf4..5e4b39f 100644 --- a/src/Oauth/TokenRequestContext.php +++ b/src/Oauth/TokenRequestContext.php @@ -48,7 +48,7 @@ public function getTenantId(): string; /** * Set the identity of the user/application. This is used as the unique cache key - * For delegated permissions the key is {tenantId}-{clientId}-{userId} + * For delegated permissions the key is {tenantId}-{clientId}-{accessTokenHash} * For application permissions, they key is {tenantId}-{clientId} * @param AccessToken|null $accessToken * @return void @@ -57,7 +57,7 @@ public function setCacheKey(?AccessToken $accessToken = null): void; /** * Return the identity of the user/application. This is used as the unique cache key - * For delegated permissions the key is {tenantId}-{clientId}-{userId} + * For delegated permissions the key is {tenantId}-{clientId}-{accessTokenHash} * For application permissions, they key is {tenantId}-{clientId} * * @return string|null diff --git a/tests/Cache/InMemoryAccessTokenCacheTest.php b/tests/Cache/InMemoryAccessTokenCacheTest.php index 3e1b127..0b96771 100644 --- a/tests/Cache/InMemoryAccessTokenCacheTest.php +++ b/tests/Cache/InMemoryAccessTokenCacheTest.php @@ -4,6 +4,7 @@ use League\OAuth2\Client\Token\AccessToken; use Microsoft\Kiota\Authentication\Cache\InMemoryAccessTokenCache; +use Microsoft\Kiota\Authentication\Oauth\AuthorizationCodeContext; use Microsoft\Kiota\Authentication\Oauth\ClientCredentialContext; use Microsoft\Kiota\Authentication\Oauth\TokenRequestContext; use PHPUnit\Framework\TestCase; @@ -58,4 +59,15 @@ public function testWithTokenAddsMultipleTokensToCache() { $this->assertInstanceOf(AccessToken::class, $cache->getTokenWithContext($this->testTokenRequestContext)); $this->assertInstanceOf(AccessToken::class, $cache->getTokenWithContext($secondContext)); } + + public function testCacheKeyIsSetForNonJWTToken() { + $accessToken = $this->createMock(AccessToken::class); + $accessToken->method('getToken')->willReturn('token'); + + $cache = new InMemoryAccessTokenCache(); + $delegatedTokenRequestContext = new AuthorizationCodeContext("tenantId", "clientId", "clientSecret", "redirectUri", "code"); + $cache->withToken($delegatedTokenRequestContext, $accessToken); + + $this->assertNotEmpty($delegatedTokenRequestContext->getCacheKey()); + } }