another invalid_client issue

We have begun implementing Sign in with Apple in our mobile app but cannot seem to call the token endpoint successfully (https://appleid.apple.com/auth/token). The response we get is 400 with the body [{"error":"invalid_client"}]. I have read and re-read the details on how to generate the client-secret. We are using a java backend and specifically the nimbus library to create the signed JWT.


final JWSHeader clientSecretHeader = 
  new JWSHeader.Builder(JWSAlgorithm.ES256)
   .keyID("7N5XJ*****")
   .build();
final Date issuedAtTime = Date.from(Instant.now());
final Date expirationTime = Date.from(Instant.now().plusSeconds(3600));
final JWTClaimsSet clientSecretClaims = 
  new JWTClaimsSet.Builder()
   .issuer("HL46P*****")
   .issueTime(issuedAtTime)
   .expirationTime(expirationTime)
   .audience("https://appleid.apple.com")
   .subject("com.company.app")
   .build();
final ECPrivateKey signingKey = ...private key loaded from p8 file...;
final JWSSigner jwtSigner = new ECDSASigner(signingKey);
final SignedJWT clientSecretJwt = new SignedJWT(clientSecretHeader, clientSecretClaims);
clientSecretJwt.sign(jwtSigner);

MultiValueMap<string, string=""> map= new LinkedMultiValueMap<>();
map.add("grant_type", "authorization_code");
map.add("client_id", "HL46P*****");
map.add("client_secret", clientSecretJwt.serialize());
map.add("code", "code receiged from app...");
final HttpEntity<multivaluemap<string, string="">> request = new HttpEntity<>(map);

final RestTemplate restTemplate = new RestTemplateBuilder().build();
final ResponseEntity response = response = restTemplate.postForEntity(
  "https://appleid.apple.com/auth/token",
  request,
  GetTokenResponse.class
 );


The resulting JWT looks like the following:


Header

{
  "kid": "7N5XJ*****",
  "alg": "ES256"
}

Claims

{
  "aud": "https://appleid.apple.com",
  "sub": "com.company.app",
  "iss": "HL46P.....",
  "exp": 1585583898,
  "iat": 1585580298
}


I am out of ideas on what we are doing wrong.

Replies

I'm having the same issues. Also trying to do this from a Java Backend. The responses generated for this API are terrible! They don't help us figure out what's wrong at all, just the same generic error: "invalid_client". Even Facebook's APIs are more descriptive.

My guess would be the signature generation part might be incorrect, which generated DER encoded format instead of the raw concatenation of the R and S values, as explained further in this StackOverflow answer.
You can generate the public key of your .p8 private key by running this code in the terminal :

openssl ec -in AuthKey_123ABC456.p8 -pubout -out AuthKey_123ABC456_Public.p8


Then using the public key generated, you can paste your client secret JWT in https://jwt.io/#debugger , and paste the public key to check if the signature verification succeed. If it fails, it mean that there's something wrong with signature generation.

Dear Developers,


I have the same issue with "invilad_error", I use postman to send my request(my code also have same response) here is the detail

url: https://appleid.apple.com/auth/token

header:

{

"Content-Type": "application/x-www-form-urlencoded",

"User-Agent": "myapp"

}

body:

{

"client_id": "xxxxxxx", //the bundle id

"client_secret": "xxxxxxxx", //generate by my code(I have changed the iat and exp in different values), and it is verified successfully in https://jwt.io/#debugger

"grant_type": "authorization_code",

"code": "xxxxxxxxx" //come from the app

}


I am wondering if there anything else need to set in develop account in the official web of apple, but no idea with it.

Just to confirm, did you generate the public key using your .p8 private key, and use that public key in https://jwt.io/#debugger to verify that the signature of your generated client secret is correct?
Another suggestion from me would be to remove the "User-Agent" header and see if it works

I had the same issue. The JWT verification is fine. Turn out my team_id used for generating private key is incorrect. I paste my apple id name, instead of team_id. The problem solved after using the right team_id.