{"record":{"id":"7bd994c96bf01f61","repo":"ory/kratos","slug":"private-key-is-not-ecdsa-key","errorCode":null,"errorMessage":"Private key is not ecdsa key","messagePattern":"Private key is not ecdsa key","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"selfservice/strategy/oidc/provider_apple.go","lineNumber":57,"sourceCode":"\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),\n\t\t\tIssuedAt:  jwt.NewNumericDate(now),\n\t\t\tIssuer:    a.config.TeamId,\n\t\t\tSubject:   a.config.ClientID,\n\t\t})\n\tappleToken.Header[\"kid\"] = a.config.PrivateKeyId\n\n\treturn appleToken.SignedString(privateKey)\n}\n","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/ory/kratos/blob/b86338da04a040247a07f46100a86dcfb3875909/selfservice/strategy/oidc/provider_apple.go#L39-L75","documentation":"After PEM decoding, newClientSecret parses the DER bytes with x509.ParsePKCS8PrivateKey and asserts the result is an *ecdsa.PrivateKey, because Apple client-secret JWTs are signed with ES256. If the PKCS8 payload decodes to any other key type (RSA, Ed25519), this error is returned.","triggerScenarios":"The Apple provider's private key is a valid PKCS8 PEM block but contains a non-ECDSA key (e.g. an RSA key from another provider), so the type assertion parsedKey.(*ecdsa.PrivateKey) fails.","commonSituations":"Wrong key pasted from a different OIDC provider; a regenerated Apple key in an unexpected algorithm; test fixtures using RSA keys.","solutions":["Use Apple's ES256 (.p8) ECDSA private key downloaded from the Apple developer portal","Verify with: openssl pkey -in apple.p8 -text -noout (should say 'Private-Key: (256 bit)' with ASN1 OID prime256v1)","Generate a fresh .p8 key in Apple Developer console if the current one is not ECDSA"],"exampleFix":"// before\n\"apple\": {\"private_key\": \"<rsa pkcs8 pem>\"}\n// after\n\"apple\": {\"private_key\": \"-----BEGIN PRIVATE KEY-----\\n<base64 EC PRIVATE KEY (prime256v1)>\\n-----END PRIVATE KEY-----\"}","handlingStrategy":"validation","validationCode":"b, _ := pem.Decode([]byte(privKey)); k, err := x509.ParsePKCS8PrivateKey(b.Bytes); if _, ok := k.(*ecdsa.PrivateKey); !ok { return errors.New(\"apple key must be ECDSA P-256\") }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Verify key algorithm with openssl pkey -text before deploying","Only use Apple .p8 keys for the Apple provider","Never reuse keys from other OIDC providers"],"tags":["go","oidc","apple-signin","ecdsa","jwt"],"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"}