{"record":{"id":"edd1262ccc8e176e","repo":"n8n-io/n8n","slug":"the-certificate-field-must-contain-a-pem-certifica","errorCode":null,"errorMessage":"The Certificate field must contain a PEM certificate (-----BEGIN CERTIFICATE-----).","messagePattern":"The Certificate field must contain a PEM certificate \\(-----BEGIN CERTIFICATE-----\\)\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/@n8n/utils/src/client-assertion.ts","lineNumber":27,"sourceCode":"import { formatPemBlock } from './format-pem-block';\n\n// private_key_jwt (RFC 7521/7523): the client proves its identity with a JWT\n// signed by its private key instead of a shared secret. The `x5t` header (SHA-1\n// thumbprint of the certificate) tells the server which public key verifies it.\nexport const CLIENT_ASSERTION_TYPE = 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer';\n\nconst ASSERTION_TTL_SECONDS = 300;\n\nfunction base64url(input: Buffer | string): string {\n\treturn Buffer.from(input).toString('base64url');\n}\n\nfunction certificateThumbprint(certificate: string): string {\n\tlet parsed: X509Certificate;\n\ttry {\n\t\tparsed = new X509Certificate(formatPemBlock(certificate));\n\t} catch (error) {\n\t\tthrow new Error(\n\t\t\t'The Certificate field must contain a PEM certificate (-----BEGIN CERTIFICATE-----).',\n\t\t\t{ cause: error },\n\t\t);\n\t}\n\treturn Buffer.from(parsed.fingerprint.replace(/:/g, ''), 'hex').toString('base64url');\n}\n\nexport interface BuildClientAssertionOptions {\n\tclientId: string;\n\t/** Token endpoint; used as the JWT `aud`. */\n\taccessTokenUri: string;\n\t/** RSA private key (PEM). Signing is RS256-only; EC/Ed25519 keys are not supported. */\n\tprivateKey: string;\n\tcertificate: string;\n}\n\nexport function buildClientAssertion(options: BuildClientAssertionOptions): string {\n\tconst now = Math.floor(Date.now() / 1000);","sourceCodeStart":9,"sourceCodeEnd":45,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/utils/src/client-assertion.ts#L9-L45","documentation":"Thrown by certificateThumbprint in buildClientAssertion when `new X509Certificate(formatPemBlock(cert))` raises. The wrapper message tells the caller the certificate field must be a PEM certificate; the original crypto error is preserved as `cause`. The certificate is used to compute the x5t (SHA-1 thumbprint) JWT header.","triggerScenarios":"Passing an empty certificate string, a private key PEM instead of a certificate PEM, a DER/base64 blob without the BEGIN CERTIFICATE markers, a certificate for the wrong key, or a malformed/truncated PEM.","commonSituations":"Uploading the private key into the certificate field by mistake in a config UI; copy-paste truncating the END marker; using a self-signed cert in a format Node's crypto cannot parse; passing a cert chain where a single leaf is expected without formatPemBlock-friendly input.","solutions":["Verify the certificate begins with '-----BEGIN CERTIFICATE-----' and ends with the matching END marker.","Ensure you are passing the public certificate, not the private key.","Validate with `openssl x509 -in cert.pem -noout` before configuring.","Inspect err.cause for the underlying crypto reason to pinpoint the format issue."],"exampleFix":"// before\nbuildClientAssertion({ ..., certificate: privateKeyPem }); // wrong field content\n// after\nbuildClientAssertion({ ..., certificate: publicCertPem }); // -----BEGIN CERTIFICATE-----...","handlingStrategy":"validation","validationCode":"function assertValidCertificatePem(cert: string): void {\n  if (!cert || !/-----BEGIN CERTIFICATE-----/.test(cert) || !/-----END CERTIFICATE-----/.test(cert)) {\n    throw new Error('certificate must be a PEM string bounded by BEGIN/END CERTIFICATE markers');\n  }\n  // optionally verify it parses:\n  new X509Certificate(cert); // throws on malformed input\n}","typeGuard":"function looksLikePemCertificate(v: unknown): v is string {\n  return typeof v === 'string'\n    && /-----BEGIN CERTIFICATE-----[\\s\\S]*-----END CERTIFICATE-----/.test(v);\n}","tryCatchPattern":"try {\n  return buildClientAssertion(opts);\n} catch (e) {\n  if (/must contain a PEM certificate/i.test(e?.message ?? '')) {\n    throw new ConfigError('certificate field is not a valid PEM certificate', { cause: e });\n  }\n  throw e;\n}","preventionTips":["Validate the PEM markers before calling buildClientAssertion.","Keep the certificate (public) and private key fields clearly labeled in config UIs.","Verify with `openssl x509 -in cert.pem -noout` during onboarding."],"tags":["n8n-utils","jwt","oauth","crypto","certificate","validation"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}