passbolt/passbolt_api · error · InternalErrorException
Cannot parse JWKS endpoint response.
Error message
Cannot parse JWKS endpoint response.
What it means
AzureProvider::getJwtVerificationKeys() fetches the JWKS (public keys) document from Azure's discovery config via getParsedResponse(); any Throwable (network error, HTTP error, JSON parse failure) is wrapped in InternalErrorException with this message, since verification keys are mandatory for validating ID tokens.
Solutions
- Test connectivity from the server: curl the JWKS URI found in the OpenID config
- Configure outbound proxy/firewall rules to allow HTTPS to login.microsoftonline.com
- Clear cached OpenID metadata and retry the SSO setup to refresh the keys URI
- Check the wrapped exception in the log for the underlying network/parse cause
Example fix
// server-side connectivity check // before: request fails silently behind firewall // after: allow egress curl -i https://login.microsoftonline.com/common/discovery/v2.0/keys
Defensive patterns
Strategy: retry
Validate before calling
$response = Http::get($keysUri); if (!$response->isOk() || !is_array($response->getJson()['keys'] ?? null)) { /* JWKS unreachable, retry/degrade */ } Type guard
function isValidJwks(mixed $response): bool { return is_array($response) && isset($response['keys']) && is_array($response['keys']); } Try / catch
try { $keys = $provider->getJwtVerificationKeys(); } catch (InternalErrorException $e) { Log::error('JWKS fetch failed: ' . $e->getPrevious()?->getMessage()); return $this->respondError(503, 'Unable to reach identity provider keys.'); } Prevention
- Guarantee outbound HTTPS from the server to Azure endpoints
- Configure proxy env vars (HTTPS_PROXY) where needed
- Cache JWKS with a sensible TTL and refresh on failure
- Alert on JWKS fetch failures before users attempt SSO
When it happens
Trigger: HTTP request to the JWKS URI fails or the response cannot be parsed — DNS failure, TLS error, timeout, 4xx/5xx from Azure, or non-JSON body.
Common situations: Server has no outbound internet access or blocked by firewall; proxy required but not configured; Azure jwks URI temporarily unreachable; discovery document cached with an outdated keys URI; clock/TLS issues on the server.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- Cannot parse JWKS endpoint response.
- Invalid JWKS endpoint response. Keys missing.
- No JWT key defined for Azure service.
- The tid (tenant id) parameter is invalid.
- The ver (version) parameter is invalid.
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/b382e6791a61c70c.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/PassboltEe/Sso/src/Utility/Azure/Provider/AzureProvider.php:169
}
/**
* Get JWT verification keys from Azure Active Directory.
*
* @return array
*/
public function getJwtVerificationKeys(): array
{
$openIdConfiguration = $this->getOpenIdConfiguration();
$keysUri = $openIdConfiguration['jwks_uri'];
$factory = $this->getRequestFactory();
$request = $factory->getRequestWithOptions('get', $keysUri, []);
try {
$response = $this->getParsedResponse($request);
} catch (Throwable $exception) {
throw new InternalErrorException(__('Cannot parse JWKS endpoint response.'), 500, $exception);
}
if (!is_array($response) || !isset($response['keys'])) {
throw new InternalErrorException(__('Invalid JWKS endpoint response. Keys missing.'));
}
/**
* Here we are using custom method to check JWK key signature as we can't use `JWK::parseKeySet` method directly
* because Azure don't provide "kty" parameter in the keys.
*
* @see \Firebase\JWT\JWK::parseKeySet()
*/
return $this->parseJwksKeys($response['keys']);
}
/**
* Parse & check JWT keys signature from Azure.
*View on GitHub (pinned to 31c1bbc10f)