invalid_client for authorization_code

I am having a hard time figuring out how to use the sign in with Apple. The documentation is terrible and failed responses leaves us clueless. The article of Aaron Parecki (https://developer.okta.com/blog/2019/06/04/what-the-heck-is-sign-in-with-apple) does help a little, but I seem stuck now.


At first, I generate a login URL with /auth/authorize like so:


$_SESSION['state'] = bin2hex(openssl_random_pseudo_bytes(16));

return 'https://appleid.apple.com/auth/authorize?' . http_build_query([
  'response_type' => 'code',
  'response_mode' => 'form_post',
  'client_id' => 'com.my.service.id',
  'redirect_uri' => 'https://my.app/redirect'),
  'state' => $_SESSION['state'],
  'scope' => 'name email',
]);


After struggling with the domain verification and return URLs, this brings me to the Apple login page and returns to my redirect_uri after succesfull login. Then, I need to authorize the token which I execute using Guzzle:


$response = (new Client)->request('POST', 'https://appleid.apple.com/auth/token', [
  RequestOptions::FORM_PARAMS => [
    'grant_type' => 'authorization_code',
    'code' => $_POST['code'],
    'redirect_uri' => 'https://my.app/redirect',
    'client_id' => 'com.my.service.id',
    'client_secret' => $this->getClientSecret(),
  ],
  RequestOptions::HEADERS => [
    'Accept' => 'application/json'
  ]
]);

return json_decode($response, true);


The client secret is generated using Firebase php-jwt (https://github.com/firebase/php-jwt) and is valid through jwt.io:


$key = openssl_pkey_get_private('file://certificate.p8');

return JWT::encode([
  'iss' => 'APPLETEAMID',
  'iat' => time(),
  'exp' => time() + 3600,
  'aud' => 'https://appleid.apple.com',
  'sub' => 'com.my.service.id',
], $key, 'ES256', 'certificate-id');


However, executing the token request to Apple returns a 400 error with the message 'invalid_client'. I cannot figure out if my client-id/secret is wrong or the code from the redirect is invalid. Can someone point me in the right direction?

Replies

I am seeing the same issue. I use jwt to create my client secret as shown below.


....

encoded = jwt.encode(tokenPayload, key=apl_private_key, algorithm='ES256', headers=tokenHeaders)

....


where the tokenPayload is set with


tokenPayload = {

"iss": <My Team Id>,

"iat": dt,

"exp": dt + 864000,

"aud": "https://appleid.apple.com",

"sub": "com.<my client Id>"

}


I have two client ids - a parent client id and a service id. I have tried both and set the client_id in the POST message to the same client id as that is used in client_secret.


Can someone please help?


- Ajay

  • Hi! Did you figure it out?

Add a Comment

Hi Ajay


Are you using the same Id in both the front-end authorization request and the server-server to call ("sub" in the client secret) ?


If yes, please raise a Feeback Assistant request with the details of your app