https://developer.apple.com/documentation/sign_in_with_apple/sign_in_with_apple_js
1 注册一个苹果开发者账号($699)
2 在苹果开发者后台注册配置登录相关信息
注册App IDs(注意勾选 sign in with app 一栏)


注册Services ID


注册私钥, 并下载保存

<html>
<head>
<meta charset="utf8">
</head>
<body>
<script type="text/javascript" src="https://appleid.cdn-apple.com/appleauth/static/jsapi/appleid/1/en_US/appleid.auth.js"></script>
<div style="width: 100px; height:100px">
<div id="appleid-signin" data-color="red" data-border="false" data-type=""></div>
</div>
<script type="text/javascript">
AppleID.auth.init({
clientId : 'club.laoqiange',
scope : 'name',
redirectURI: 'https://www.laoqiange.club/apple-login.php',
state : 'dfadfaf'
});
</script>
</body>
</html>
4. 编写回调服务器的代码
https://developer.apple.com/documentation/sign_in_with_apple/sign_in_with_apple_rest_api
<?php
//header("Refresh:5;url=https://www.laoqiange.club?id=1");
echo "1.苹果传递的参数,post 方法<br>";
echo "<pre>";
var_dump($_POST);
echo "</pre>";
echo "\r\n";
echo "可以让后端在这个页面处理玩逻辑之后,重定向到个人中心页面<br>".PHP_EOL;
include 'vendor/autoload.php';
use \Firebase\JWT\JWT;
use \Firebase\JWT\JWK;
$header = [
"kid" => "JF377CR8TB"
];
$payload = [
"iss" => "M8F55JTVXX",
"iat" => time(),
"exp" => time() + 86400 * 180,
"aud" => "https://appleid.apple.com",
"sub" => "club.laoqiange"
];
$privateKey = file_get_contents('./AuthKey_JF377CR8TB.p8');
// 2. 生成 client_secret
$client_secret = Jwt::encode($payload, $privateKey, 'ES256', 'JF377CR8TB');
echo '2. 生成client_secret<br>';
// 3. 请求获取token
$response = http('https://appleid.apple.com/auth/token', [
'grant_type' => 'authorization_code',
'code' => $_POST['code'],
'redirect_uri' => 'https://www.laoqiange.club/apple-login.php',
'client_id' => 'club.laoqiange',
'client_secret' => $client_secret
]);
echo '<pre>';
echo '3. 请求获取token 返回<br>';
var_dump($response);
echo '</pre>';
$id_token = $response['id_token'];
$verifyKeys = http('https://appleid.apple.com/auth/keys');
$verifyKeyA = JWK::parseKeySet($verifyKeys);
$info = JWT::decode($id_token, $verifyKeyA, ['RS256']);
echo '<pre>';
echo '4. 解密校验id_token, 获取apple账号标志符<br>';
var_dump($info);
echo '</pre>';
function http($url, $params=false) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
if($params)
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Accept: application/json',
'User-Agent: curl', # Apple requires a user agent header at the token endpoint
]);
$response = curl_exec($ch);
if ($response === false) {
echo curl_errno($ch);
exit(2);
}
$status = curl_getinfo($ch);
return json_decode($response, true);
}
首次授权登录的信息截图

再次授权登录页面

5 注意事项
(1)首次授权登录的会受到用户的账号信息,再次登录的时候不会带着,如果需要,要在第一次的时候存于数据库,对比图E和图F的第一条。
(2)前端代码里面 clientId 是 图C的 idenfiter( Services ID )。
(3)appleid 的唯一用户标志服符是 id_token 解密后 payload的 sub 字段。 https://developer.apple.com/documentation/sign_in_with_apple/sign_in_with_apple_rest_api/authenticating_users_with_sign_in_with_apple
(4)jwt 可以参考网站 https://jwt.io/
(5)如果只需要 apple账号唯一标志符,可以不需要后端。第一步授权之后也能拿到的id_token, js也可以把它解析出来。
(6) 第4步 php用到了 https://github.com/firebase/php-jwt 这个composer类
6 demo
