{"record":{"id":"384eb9a1af622329","repo":"passbolt/passbolt_api","slug":"the-jwt-public-key-could-not-be-extracted","errorCode":null,"errorMessage":"The JWT public key could not be extracted.","messagePattern":"The JWT public key could not be extracted\\.","errorType":"http","errorClass":"InvalidJwtKeyPairException","httpStatus":500,"severity":"critical","filePath":"plugins/PassboltCe/JwtAuthentication/src/Service/AccessToken/JwksGetService.php","lineNumber":64,"sourceCode":"     * @return int\n     */\n    public function getSecretKeySize(): int\n    {\n        $details = $this->getDetails();\n\n        return $details['bits'] ?? 0;\n    }\n\n    /**\n     * @return array\n     * @throws \\Passbolt\\JwtAuthentication\\Error\\Exception\\AccessToken\\InvalidJwtKeyPairException if the public key file is not parsable.\n     */\n    private function getDetails(): array\n    {\n        $pubKey = $this->readKeyFileContent();\n        $res = openssl_pkey_get_public($pubKey);\n        if ($res === false) {\n            throw new InvalidJwtKeyPairException(__('The JWT public key could not be extracted.'));\n        }\n        $details = openssl_pkey_get_details($res);\n        if ($details === false) {\n            throw new InvalidJwtKeyPairException(__('The JWT public key details could not be read.'));\n        }\n\n        return $details;\n    }\n\n    /**\n     * @return string|false\n     * @throws \\Passbolt\\JwtAuthentication\\Error\\Exception\\AccessToken\\InvalidJwtKeyPairException if the public key file is not found or not readable.\n     */\n    public function getRawPublicKey(): string|false\n    {\n        return $this->readKeyFileContent();\n    }\n}","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltCe/JwtAuthentication/src/Service/AccessToken/JwksGetService.php#L46-L82","documentation":"Thrown by JwksGetService::getDetails when openssl_pkey_get_public() fails to parse the JWT public key file contents into a usable OpenSSL key resource. This signals the PEM file at the configured jwt key path is corrupt, empty, or not a valid public key.","triggerScenarios":"Building the JWKS (getPublicKey/getSecretKeySize) when the jwt.public.key file contains garbage, an HTML error page, an encrypted key, or truncated content.","commonSituations":"Key pair generation failed or was interrupted; file overwritten during deployment; wrong file mounted (e.g. private key expected but public slot holds something else); copy/paste artifacts in the PEM.","solutions":["Regenerate the JWT key pair: bin/cake passbolt create_jwt_keys","Verify the PEM content: openssl pkey -pubin -in config/jwt/jwt.public.key -text -noout","Check file permissions/readability for the web server user and that the file isn't empty","If keys come from env/secret mount, confirm the secret contents are the full PEM, not base64 or truncated"],"exampleFix":"// regenerate\nbin/cake passbolt create_jwt_keys\n// verify\nopenssl pkey -pubin -in config/jwt/jwt.public.key -noout","handlingStrategy":"validation","validationCode":"$pub = file_get_contents($path);\nif (empty($pub) || openssl_pkey_get_public($pub) === false) {\n    throw new RuntimeException('jwt.public.key invalid at ' . $path);\n}","typeGuard":null,"tryCatchPattern":"try { $jwks = $service->getPublicKey(); } catch (InvalidJwtKeyPairException $e) { regenerateKeys(); }","preventionTips":["Run create_jwt_keys during provisioning, idempotently","Validate PEMs with openssl at deploy time","Mount secrets as raw PEM, never base64-wrapped or truncated"],"tags":["jwt","openssl","key-pair","configuration"],"backgroundTag":"invalid-key-format","analyzedSha":"31c1bbc10f32808a607fa9bd81891e898779c0bc","analyzedAt":"2026-09-17T00:04:38.960Z","contentChangedAt":"2026-09-17T00:04:38.960Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}