{"record":{"id":"efb6ff8cb019ff0c","repo":"ory/kratos","slug":"failed-to-decode-pem-block-containing-private-key","errorCode":null,"errorMessage":"failed to decode PEM block containing private key","messagePattern":"failed to decode PEM block containing private key","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"selfservice/strategy/oidc/provider_apple.go","lineNumber":48,"sourceCode":"func NewProviderApple(\n\tconfig *Configuration,\n\treg Dependencies,\n) Provider {\n\tconfig.IssuerURL = \"https://appleid.apple.com\"\n\treturn &ProviderApple{\n\t\tProviderGenericOIDC: &ProviderGenericOIDC{\n\t\t\tconfig: config,\n\t\t\treg:    reg,\n\t\t},\n\t\tJWKSUrl: \"https://appleid.apple.com/auth/keys\",\n\t}\n}\n\nfunc (a *ProviderApple) newClientSecret() (string, error) {\n\t// decode the pem format\n\tblock, _ := pem.Decode([]byte(a.config.PrivateKey))\n\tif block == nil || block.Type != \"PRIVATE KEY\" {\n\t\treturn \"\", errors.New(\"failed to decode PEM block containing private key\")\n\t}\n\n\tparsedKey, err := x509.ParsePKCS8PrivateKey(block.Bytes)\n\tif err != nil {\n\t\treturn \"\", errors.Wrap(err, \"Private key decoding failed\")\n\t}\n\tprivateKey, ok := parsedKey.(*ecdsa.PrivateKey)\n\tif !ok {\n\t\treturn \"\", errors.New(\"Private key is not ecdsa key\")\n\t}\n\n\tnow := time.Now()\n\texpirationTime := time.Now().Add(5 * time.Minute)\n\n\tappleToken := jwt.NewWithClaims(jwt.SigningMethodES256,\n\t\tjwt.RegisteredClaims{\n\t\t\tAudience:  []string{\"https://appleid.apple.com\"},\n\t\t\tExpiresAt: jwt.NewNumericDate(expirationTime),","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/ory/kratos/blob/b86338da04a040247a07f46100a86dcfb3875909/selfservice/strategy/oidc/provider_apple.go#L30-L66","documentation":"ProviderApple.newClientSecret decodes the configured Apple private key with pem.Decode and requires a PEM block of type 'PRIVATE KEY'. If the stored value is not valid PEM or the block type differs, it returns this error instead of proceeding to PKCS8 parsing. This happens when the Apple Sign-in .p8 key is not stored in proper PEM form in configuration.","triggerScenarios":"Configuring the Apple OIDC provider with a private_key value that is raw base64/DER bytes without the BEGIN/END PEM armor, or a PEM block whose Type is not exactly 'PRIVATE KEY' (e.g. 'EC PRIVATE KEY').","commonSituations":"Admins paste the .p8 key content without the '-----BEGIN PRIVATE KEY-----' header; newline characters are stripped when the key is stored in an environment variable; an old pem-encoded key in a different format (PKCS1) is used.","solutions":["Store the full PEM text including '-----BEGIN PRIVATE KEY-----' and '-----END PRIVATE KEY-----' lines","When using an env var, keep newlines as \\n escapes and ensure the config loader expands them, or base64-wrap it if supported","Verify the block type is 'PRIVATE KEY' (PKCS8); convert PKCS1 'EC PRIVATE KEY' keys with: openssl pkcs8 -topk8 -nocrypt -in apple.p8","Trim whitespace/newline mangling caused by YAML/env transport"],"exampleFix":"// before\n\"private_key\": \"MIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEB...\"\n// after\n\"private_key\": \"-----BEGIN PRIVATE KEY-----\\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEB...\\n-----END PRIVATE KEY-----\"","handlingStrategy":"validation","validationCode":"if !strings.Contains(privKey, \"-----BEGIN PRIVATE KEY-----\") { return errors.New(\"apple private_key must be PKCS8 PEM with BEGIN/END PRIVATE KEY armor\") }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep the .p8 key in PEM form end-to-end; never strip the armor lines","Use \\n escapes in env vars and ensure config expands them","Validate at startup with pem.Decode before first OAuth call","Convert non-PKCS8 keys with openssl pkcs8"],"tags":["go","oidc","apple-signin","pem"],"backgroundTag":"missing-credentials","analyzedSha":"b86338da04a040247a07f46100a86dcfb3875909","analyzedAt":"2026-09-07T15:58:15.934Z","contentChangedAt":"2026-09-07T15:58:15.934Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}