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