Repository: symfony/symfony
File: src/Symfony/Component/Security/Http/AccessToken/Oidc/OidcTokenHandler.php (PHP)

Code before:
    public function enableDiscovery(CacheInterface $cache, HttpClientInterface $client, string $oidcConfigurationCacheKey, string $oidcJWKSetCacheKey): void
    {
        $this->discovery[] = [
            'cache' => $cache,
            'client' => $client,
            'oidcConfigurationCacheKey' => $oidcConfigurationCacheKey,
            'oidcJWKSetCacheKey' => $oidcJWKSetCacheKey,
        ];
    }

    public function getUserBadgeFrom(string $accessToken): UserBadge
    {
        if (!class_exists(JWSVerifier::class) || !class_exists(Checker\HeaderCheckerManager::class)) {
            throw new \LogicException('You cannot use the "oidc" token handler since "web-token/jwt-signature" and "web-token/jwt-checker" are not installed. Try running "composer require web-token/jwt-signature web-token/jwt-checker".');
        }

        if (!$this->discovery && !$this->signatureKeyset) {
            throw new \LogicException('You cannot use the "oidc" token handler without JWKSet nor "discovery". Please configure JWKSet in the constructor, or call "enableDiscovery" method.');
        }

        $jwkset = $this->signatureKeyset;
        if ($this->discovery) {
            $jwkset = new JWKSet([]);
            foreach ($this->discovery as ['cache' => $discoveryCache, 'client' => $discoveryClient, 'oidcConfigurationCacheKey' => $oidcConfigurationCacheKey, 'oidcJWKSetCacheKey' => $oidcJWKSetCacheKey]) {
                try {
                    $oidcConfiguration = json_decode($discoveryCache->get($oidcConfigurationCacheKey, function () use ($discoveryClient): string {
                        $response = $discoveryClient->request('GET', '.well-known/openid-configuration');

                        return $response->getContent();
                    }), true, 512, \JSON_THROW_ON_ERROR);
                } catch (\Throwable $e) {
                    $this->logger?->error('An error occurred while requesting OIDC configuration.', [
                        'error' => $e->getMessage(),
                        'trace' => $e->getTraceAsString(),
                    ]);

                    throw new BadCredentialsException('Invalid credentials.', $e->getCode(), $e);
                }

                try {
                    $json = $discoveryCache->get($oidcJWKSetCacheKey, function () use (
                        $discoveryClient,
                        $oidcConfiguration): string {
                        $response = $discoveryClient->request('GET', $oidcConfiguration['jwks_uri']);
                        // we only need signature key
                        $keys = array_filter($response->toArray()['keys'], static fn (array $key) => 'sig' === $key['use']);

                        return json_encode(['keys' => $keys]);
                    });

                    foreach (JWKSet::createFromJson($json) as $key) {

Review comment (performance):
```suggestion
                    $oidcConfiguration = json_decode($discoveryCache->get($oidcConfigurationCacheKey, static function () use ($discoveryClient): string {
```

Code after:
     */
    public function enableDiscovery(CacheInterface $cache, array|HttpClientInterface $client, string $oidcConfigurationCacheKey, ?string $oidcJWKSetCacheKey = null): void
    {
        if (null !== $oidcJWKSetCacheKey) {
            trigger_deprecation('symfony/security-http', '7.4', 'Passing $oidcJWKSetCacheKey parameter to "%s()" is deprecated.', __METHOD__);
        }

        $this->discoveryCache = $cache;
        $this->discoveryClients = \is_array($client) ? $client : [$client];
        $this->oidcConfigurationCacheKey = $oidcConfigurationCacheKey;
    }

    public function getUserBadgeFrom(string $accessToken): UserBadge
    {
        if (!class_exists(JWSVerifier::class) || !class_exists(Checker\HeaderCheckerManager::class)) {
            throw new \LogicException('You cannot use the "oidc" token handler since "web-token/jwt-signature" and "web-token/jwt-checker" are not installed. Try running "composer require web-token/jwt-signature web-token/jwt-checker".');
        }

        if (!$this->discoveryClients && !$this->signatureKeyset) {
            throw new \LogicException('You cannot use the "oidc" token handler without JWKSet nor "discovery". Please configure JWKSet in the constructor, or call "enableDiscovery" method.');
        }

        $jwkset = $this->signatureKeyset;
        if ($this->discoveryClients) {
            $clients = $this->discoveryClients;
            $logger = $this->logger;
            $keys = $this->discoveryCache->get($this->oidcConfigurationCacheKey, static function () use ($clients, $logger): array {
                try {
                    $configResponses = [];
                    foreach ($clients as $client) {
                        $configResponses[] = $client->request('GET', '.well-known/openid-configuration', [
                            'user_data' => $client,
                        ]);
                    }

                    $jwkSetResponses = [];
                    foreach ($client->stream($configResponses) as $response => $chunk) {
                        if ($chunk->isLast()) {
                            $jwkSetResponses[] = $response->getInfo('user_data')->request('GET', $response->toArray()['jwks_uri']);
                        }
                    }

                    $keys = [];
                    foreach ($jwkSetResponses as $response) {
                        foreach ($response->toArray()['keys'] as $key) {
                            if ('sig' === $key['use']) {
                                $keys[] = $key;
                            }
                        }
                    }