credentials->get(); $cacheKey = self::CACHE_PREFIX . strtoupper(hash('sha256', $credentials['client_email'])); $cached = (string)$this->cache->load($cacheKey); if ($cached !== '') { return $cached; } $now = time(); $header = ['alg' => 'RS256', 'typ' => 'JWT']; if (!empty($credentials['private_key_id'])) { $header['kid'] = $credentials['private_key_id']; } $claims = [ 'iss' => $credentials['client_email'], 'scope' => self::SCOPE, 'aud' => self::TOKEN_URL, 'iat' => $now, 'exp' => $now + 3600, ]; $unsignedJwt = $this->base64UrlEncode($this->encodeJson($header)) . '.' . $this->base64UrlEncode($this->encodeJson($claims)); $privateKey = openssl_pkey_get_private($credentials['private_key']); $signature = ''; if ($privateKey === false || !openssl_sign($unsignedJwt, $signature, $privateKey, OPENSSL_ALGO_SHA256) ) { throw new LocalizedException(__('Unable to sign the Google service account request.')); } $assertion = $unsignedJwt . '.' . $this->base64UrlEncode($signature); $client = $this->curlFactory->create(); $client->setTimeout(30); $client->setHeaders(['Content-Type' => 'application/x-www-form-urlencoded']); $client->post(self::TOKEN_URL, http_build_query([ 'grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer', 'assertion' => $assertion, ], '', '&', PHP_QUERY_RFC3986)); $response = json_decode((string)$client->getBody(), true); $token = is_array($response) ? (string)($response['access_token'] ?? '') : ''; if ($client->getStatus() < 200 || $client->getStatus() >= 300 || $token === '') { $message = is_array($response) ? (string)($response['error_description'] ?? $response['error'] ?? '') : ''; throw new LocalizedException( __('Google service account authentication failed (HTTP %1): %2', $client->getStatus(), $message ?: 'Unknown error') ); } $lifetime = max(60, min(3300, (int)($response['expires_in'] ?? 3600) - 300)); $this->cache->save($token, $cacheKey, [], $lifetime); return $token; } private function base64UrlEncode(string $value): string { return rtrim(strtr(base64_encode($value), '+/', '-_'), '='); } private function encodeJson(array $value): string { return json_encode( $value, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR ); } }