We are integrating Sign in with Apple for our web application and have been stuck on an invalid_client error during the token exchange step.
The Problem
The authorization step works fine — the user authenticates on Apple's page and a valid authorization code is returned to our callback URL. However, when we exchange that code at https://appleid.apple.com/auth/token, it returns:
{"error": "invalid_client"}
The Puzzling Part
When we send a dummy/expired authorization code with the exact same client_id and client_secret, Apple returns:
{"error": "invalid_grant", "error_description": "The code has expired or has been revoked."}
This confirms that our client credentials (client_id + client_secret JWT) are valid and accepted by Apple. The invalid_client error only occurs when a real, freshly-issued authorization code is used.
Configuration
Service ID configured with Sign in with Apple enabled
Primary App ID with Sign in with Apple capability enabled
Domain verified, Return URL registered
Key created with Sign in with Apple enabled, linked to the correct Primary App ID
Client Secret JWT
Generated per Apple's documentation:
Header: alg: ES256, kid set to our Key ID
Claims:
iss: Team ID
iat: current timestamp
exp: iat + 6 months (within Apple's limit)
aud: https://appleid.apple.com
sub: Service ID (matches the client_id used in authorization)
Signed with: the .p8 private key associated with the Key
Token Exchange Request
POST https://appleid.apple.com/auth/tokenContent-Type: application/x-www-form-urlencodedclient_id=client_secret=code=grant_type=authorization_coderedirect_uri=
What We've Tried
Standalone test endpoint — built a minimal endpoint (no framework) that does the token exchange via server-side curl. Same invalid_client.
Multiple Service IDs — created and tried 3 different Service IDs. All produce the same error with real codes.
Multiple Keys — tried 2 different keys. Same error.
Verified redirect_uri matches exactly between the authorization request and token request.
Verified client_id matches exactly between the authorization URL and token request.
Used client_secret_post (credentials in body, not Basic auth header).
Freshness — code is used immediately upon receipt (within seconds), well before the 5-minute expiry.
Filed a Developer Support case — was directed to Forums.
Summary
Scenario code Result
Dummy/expired code abc123 invalid_grant (credentials accepted)
Real fresh code from Apple callback invalid_client
This pattern suggests something goes wrong specifically when Apple validates the authorization code against the client — even though the client credentials themselves are accepted in isolation.
Has anyone encountered this behavior? Is there a known configuration issue that could cause invalid_client only with valid authorization codes?
Any guidance would be greatly appreciated.
Topic:
Privacy & Security
SubTopic:
Sign in with Apple
Tags:
Sign in with Apple REST API
Sign in with Apple
Sign in with Apple JS
0
0
39