diff --git a/README.md b/README.md index 6d9faf4..e98075f 100644 --- a/README.md +++ b/README.md @@ -130,10 +130,12 @@ kreait_firebase: database_uri: 'https://my_project.firebaseio.com' # Optional: Make the client tenant aware tenant_id: 'tenant-id' - # Optional: Used to cache Google's public keys. + # Optional: Used to cache Google's public keys for ID Token verification. verifier_cache: null # Example: cache.app # Optional: Used to cache the authentication tokens for connecting to the Firebase servers. auth_token_cache: null # Example: cache.app + # Optional: Used to cache Google's public keys for AppCheck token verification. + key_set_cache: null # Example: cache.app # Optional: Service id of Kreait\Firebase\Http\HttpClientOptions # used to configure the SDK's HTTP client. http_client_options: null # Example: app.firebase.http_client_options diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index 48a01dc..52c74d2 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -58,13 +58,18 @@ public function getConfigTreeBuilder(): TreeBuilder ->scalarNode('verifier_cache') ->defaultNull() ->example('cache.app') - ->info('Used to cache Google\'s public keys.') + ->info('Used to cache Google\'s public keys for ID Token verification.') ->end() ->scalarNode('auth_token_cache') ->defaultNull() ->example('cache.app') ->info('Used to cache the authentication tokens for connecting to the Firebase servers.') ->end() + ->scalarNode('key_set_cache') + ->defaultNull() + ->example('cache.app') + ->info('Used to cache Google\'s public keys for AppCheck token verification.') + ->end() ->scalarNode('http_client_options') ->defaultNull() ->example('app.firebase.http_client_options') diff --git a/src/DependencyInjection/Factory/ProjectFactory.php b/src/DependencyInjection/Factory/ProjectFactory.php index ba1b904..fd348af 100644 --- a/src/DependencyInjection/Factory/ProjectFactory.php +++ b/src/DependencyInjection/Factory/ProjectFactory.php @@ -15,6 +15,7 @@ class ProjectFactory { private ?CacheItemPoolInterface $verifierCache = null; private ?CacheItemPoolInterface $authTokenCache = null; + private ?CacheItemPoolInterface $keySetCache = null; private ?HttpClientOptions $httpClientOptions = null; /** @@ -41,6 +42,18 @@ public function setAuthTokenCache($authTokenCache = null): void $this->authTokenCache = $authTokenCache; } + /** + * @param CacheInterface|CacheItemPoolInterface|null $keySetCache + */ + public function setKeySetCache($keySetCache = null): void + { + if ($keySetCache instanceof CacheInterface) { + $keySetCache = new Psr16Adapter($keySetCache); + } + + $this->keySetCache = $keySetCache; + } + public function setHttpClientOptions(?HttpClientOptions $httpClientOptions = null): void { $this->httpClientOptions = $httpClientOptions; @@ -83,6 +96,10 @@ public function createFactory(array $config = []): Factory $factory = $factory->withHttpClientOptions($this->httpClientOptions); } + if ($this->keySetCache) { + $factory = $factory->withKeySetCache($this->keySetCache); + } + return $factory; } diff --git a/src/DependencyInjection/FirebaseExtension.php b/src/DependencyInjection/FirebaseExtension.php index 9890e6c..32bc0e8 100644 --- a/src/DependencyInjection/FirebaseExtension.php +++ b/src/DependencyInjection/FirebaseExtension.php @@ -70,6 +70,10 @@ private function registerProjectFactory(string $name, array $config, ContainerBu $projectFactory->addMethodCall('setAuthTokenCache', [new Reference($config['auth_token_cache'])]); } + if ($config['key_set_cache'] ?? null) { + $projectFactory->addMethodCall('setKeySetCache', [new Reference($config['key_set_cache'])]); + } + if ($config['http_client_options'] ?? null) { $projectFactory->addMethodCall('setHttpClientOptions', [new Reference($config['http_client_options'])]); } diff --git a/tests/DependencyInjection/Factory/ProjectFactoryTest.php b/tests/DependencyInjection/Factory/ProjectFactoryTest.php index 09c13a6..4e9b1e9 100644 --- a/tests/DependencyInjection/Factory/ProjectFactoryTest.php +++ b/tests/DependencyInjection/Factory/ProjectFactoryTest.php @@ -141,6 +141,15 @@ public function testItAcceptsAPSR6AuthTokenCache(): void $this->factory->createAuth($this->defaultConfig); } + #[DoesNotPerformAssertions] + public function testItAcceptsAPSR6KeySetCache(): void + { + $cache = $this->createStub(CacheItemPoolInterface::class); + + $this->factory->setKeySetCache($cache); + $this->factory->createAppCheck($this->defaultConfig); + } + #[DoesNotPerformAssertions] public function testItAcceptsHttpClientOptions(): void { diff --git a/tests/DependencyInjection/FirebaseExtensionTest.php b/tests/DependencyInjection/FirebaseExtensionTest.php index 695eb82..5c8d67b 100644 --- a/tests/DependencyInjection/FirebaseExtensionTest.php +++ b/tests/DependencyInjection/FirebaseExtensionTest.php @@ -105,6 +105,25 @@ public function testAnAuthTokenCacheCanBeUsed(): void $this->assertInstanceOf(Firebase\Contract\Auth::class, $container->get(Firebase\Contract\Auth::class)); } + public function testAKeySetCacheCanBeUsed(): void + { + $cacheServiceId = 'cache.app.simple.mock'; + + $container = $this->createContainer([ + 'projects' => [ + 'foo' => [ + 'credentials' => __DIR__.'/../_fixtures/valid_credentials.json', + 'key_set_cache' => $cacheServiceId, + ], + ], + ]); + + $cache = $this->createStub(CacheItemPoolInterface::class); + $container->set($cacheServiceId, $cache); + + $this->assertInstanceOf(Firebase\Contract\AppCheck::class, $container->get(Firebase\Contract\AppCheck::class)); + } + public function testHttpClientOptionsCanBeUsed(): void { $httpClientOptionsServiceId = 'firebase.http_client_options';