Я реализовал Apple Sign In на веб-сайте, но не могу получить полное имя пользователя. Он добавлен в область видимости, но не публикуется (отправляется только в первый раз). Есть ли способ каким-то образом это получить?
Frontend:
<div class="login-btn" id="appleid-signin" data-color="black" data-border="true" data-type="sign in"></div>
<script type="text/javascript"
src="https://appleid.cdn-apple.com/appleauth/static/jsapi/appleid/1/en_US/appleid.auth.js"></script>
<script type="text/javascript">
AppleID.auth.init({
clientId: 'net.exmample.oauth',
scope: 'email name',
response_type: 'code',
response_mode: 'form_post',
redirectURI: 'https://example.net/appletest',
usePopup : false
});
const buttonElement = document.getElementById('appleid-signin');
buttonElement.addEventListener('click', () => {
AppleID.auth.signIn();
});
</script>
Backend:
$identityToken = Input::post('id_token');
$appleSignInPayload = ASDecoder::getAppleSignInPayload($identityToken);
$email = $appleSignInPayload->getEmail();
var_dump('email: ' . $email);
echo '<br>';
$user = $appleSignInPayload->getUser();
var_dump('userid: ' . $user);
echo '<br>';
$isValid = $appleSignInPayload->verifyUser($user);
echo 'is valid : ';
var_dump($isValid);
echo '<br>';
$clientId = 'net.example.oauth';
$teamId = 'TT123';
$keyId = 'KK123';
$code = Input::post('code');
echo 'Code: ' . $code . '<br>';
$claims = [
'iss' => $teamId,
'aud' => 'https://appleid.apple.com',
'sub' => $clientId,
'iat' => time(),
'exp' => time() + 3600,
];
$headers = ['kid' => $keyId, 'alg' => 'ES256'];
$privateKey = <<<EOD-----BEGIN PRIVATE KEY-----key goes here-----END PRIVATE KEY-----EOD;
$publicKey = <<<EOD-----BEGIN PUBLIC KEY-----key goes here-----END PUBLIC KEY-----EOD;
$client_secret = JWT::encode($claims, $privateKey, 'ES256', $keyId, $headers);
// var_dump($client_secret);
$decoded = JWT::decode($client_secret, $publicKey, ['ES256']);
// var_dump($decoded);
$ch = curl_init();
$data = [
'client_id' => $clientId, // app id?
'code' => $code, //from request
'client_secret' => $client_secret,
'grant_type' => 'authorization_code',
'redirect_uri' => 'https://example.net/appletest'
];
curl_setopt($ch, CURLOPT_URL, "https://appleid.apple.com/auth/token");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$server_output = curl_exec($ch);
curl_close($ch);
$response = json_decode($server_output, true);
if ($response['access_token']) {
var_dump($response);
$appleSignInPayload = ASDecoder::getAppleSignInPayload($response['id_token']);
}
Для переполнения стека требуется более подробная информация в коде. Поэтому я могу добавить, что он использует библиотеки AppleSignIn \ ASDecoder и \ Firebase \ JWT \ JWT . Также я обнаружил, что в бэкэнде вы должны указать тот же redirect_uri, что и во фронтенде, иначе вы получите ошибку {"invalid_grant"}. Надеюсь, это сэкономит кому-то несколько часов.
Если кто-то в затруднительном положении прочитает это, вот как извлечь publi c ключ из файла .p8: openssl e c -in AuthKey_KEY_ID.p8 -pubout -out AuthKey_KEY_ID_Publi c .p8
UPD: Вроде правда, что имя получить можно только с первого раза. Я тестировал его с другом и получил ответ.
array(3) {
["code"]=> string(64) "c94b9775110randoma918bc357.0.nsqty.covC4GSS1e2O4..."
["id_token"]=> string(766) "eyJraWQiOiJlWGF1bm1MIiwiYWrandomyNTYifQ.eyJpc3MiOiJodHRwczovL2FwcGxlaW..."
["user"]=> string(82) "{"email":"e.g@example.net","name":{"firstName":"Eeee","lastName":"Ggg"}}" }
UPD 2: можно удалить приложение с помощью мобильного телефона в Настройки-> Пароли и безопасность-> Приложения с использованием вашего Apple ID. После удаления данные пользователя снова будут опубликованы. Но это хорошо только для тестирования. Обновление пользовательских данных в производственной среде все еще требует обновления профиля с течением времени.
UPD 3: Отвязать приложение от учетной записи Apple можно не только по телефону, но и на веб-сайте https://appleid.apple.com/account/manage в разделе Безопасность-> ПРИЛОЖЕНИЯ И ВЕБ-САЙТЫ, ИСПОЛЬЗУЯ APPLE ID- > Управление разделом