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?