passbolt/passbolt_api · error · InternalErrorException

No JWT key defined for Azure service.

Error message

No JWT key defined for Azure service.

What it means

Thrown by AzureProvider::parseJwksKeys after iterating all JWKS key entries when no verification key could be built ($keys is empty). Every key entry lacked a usable 'x5c' array (or the x5c loop produced nothing), so there is no key to verify Azure-issued JWTs and SSO cannot proceed.

Solutions

  1. Inspect the JWKS response (curl the jwks_uri) and confirm key entries include an 'x5c' array with base64 DER certificates.
  2. Ensure the OpenID configuration points at the correct Azure AD tenant/common discovery document whose jwks_uri serves x5c-bearing RSA keys.
  3. If keys were recently rotated, clear any cached OpenID configuration and re-fetch the JWKS.
  4. If you control the JWKS source (test fixture/custom IdP), add x5c certificate values to each RSA key entry.

Example fix

null
Defensive patterns

Strategy: validation

Validate before calling

$jwks = json_decode(file_get_contents($jwksUri), true);
$usable = array_filter($jwks['keys'] ?? [], fn($k) => isset($k['x5c']) && is_array($k['x5c']) && $k['x5c'] !== []);
if ($usable === []) {
    throw new RuntimeException('JWKS contains no x5c-bearing keys; JWT verification will fail');
}

Type guard

function jwksHasVerifiableKeys(array $keys): bool {
    foreach ($keys as $key) {
        if (isset($key['x5c']) && is_array($key['x5c']) && $key['x5c'] !== []) {
            return true;
        }
    }
    return false;
}

Try / catch

try {
    $keys = $provider->getJwtVerificationKeys();
} catch (InternalErrorException $e) {
    if ($e->getMessage() === 'No JWT key defined for Azure service.') {
        Log::error('JWKS yielded zero usable keys — check x5c presence and tenant configuration');
    }
    throw $e;
}

Prevention

When it happens

Trigger: The JWKS response contains key entries without an 'x5c' member (or with a non-array x5c), or 'keys' is an empty array — the code silently skips entries without x5c and only fails at the end with this message.

Common situations: Azure AD rotating keys or serving EC-only keys without x5c in a non-standard endpoint; a custom/alternative JWKS source (e.g. a different IdP routed through this provider) whose keys lack x5c; mock fixtures missing x5c; Azure outage returning a minimal key set.

Understand the failure class

Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.

Related errors


AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17). Data as JSON: /api/errors/a0302d4280dbf77d. Report an issue: GitHub.

Appendix: source

Thrown at plugins/PassboltEe/Sso/src/Utility/Azure/Provider/AzureProvider.php:230

                        throw new InternalErrorException($msg);
                    }

                    $pkey_array = openssl_pkey_get_details($pkey_object);

                    if ($pkey_array === false) {
                        $msg = __('Failed to public key properties from certificate: {0}', $encodedkey);
                        throw new InternalErrorException($msg);
                    }

                    $publicKey = $pkey_array['key'];

                    $keys[$keyinfo['kid']] = new Key($publicKey, 'RS256');
                }
            }
        }

        if (empty($keys)) {
            throw new InternalErrorException('No JWT key defined for Azure service.');
        }

        return $keys;
    }
}

View on GitHub (pinned to 31c1bbc10f)