Sign In With Apple服务器登录验证有很多问题,官方文档写的也不清不楚,网上资料不算多。
一、验证identityToken有效性和正确性
根据官方文档说明,identityToken是一个JWT算法格式,要使用JWT这个库去进行解析,解析完成后进行验证:
(1)Verify the JWS E256 signature using the server’s public key
(2)Verify the nonce for the authentication
(3)Verify that the iss field contains https://appleid.apple.com
(4)Verify that the aud field is the developer’s client_id
(5)Verify that the time is earlier than the exp value of the token
具体验证方法可以参考某个博客的一篇文章,我这边验证identityToken都是参考这篇博客
try {
$identityToken = $verifyArray['identityToken'];
$appleSignInPayload = ASDecoder::getAppleSignInPayload($identityToken);
$email = $appleSignInPayload->getEmail();
$user = $appleSignInPayload->getUser();
$userId = $verifyArray['user'];
$isValid = $appleSignInPayload->verifyUser($userId);
// print_r($isValid);
if (!$isValid){
if($errDesc ==''){
$errDesc = 'verify userId fail';
}
}
return $appleSignInPayload;
}catch (Exception $exception){
// print_r($exception->getMessage());
if($errDesc ==''){
$errDesc = $exception->getMessage();
}
return null;
}
二、authorizationCode验证,生成和刷新token
主要是authorizationCode验证,我很怀疑这个是web Sign In With Apple的时候才需要用到。
具体接口文档
1.苹果后台创建一个密钥,用于获取我们的 client_secret,这也是从 Apple 发出令牌请求所必需的。
(1) 进入 Certificates, Identifiers & Profiles > Keys,然后单击 Keys 旁边左上角的 + 号。
(2)提供密钥名称并确保勾选 Sign In with Apple。在这里,我们还必须单击 Configure。在接下来出现的Configure Key 面板中,选择我们之前在 Choose a Primary App ID 下使用的 App ID,然后单击“保存”。
(3) 单击 Continue,然后在下一页中验证详细信息并单击 Register。
(4)下载密钥并将其保存在安全的地方,因为您永远无法再次下载密钥。下载密钥后单击 Done。
(5)保存key id和获取开发者账号的TeamID,后面需要使用这两个值。
2.生成client_secret,需要使用jwt库,规定生成的JWT最长期限为6个月,你可以手动生成 JWT,但是不能使用firebase/php-jwt这个库,因为这个库缺少支持ES256算法格式,如果使用最后请求https://appleid.apple.com/auth/token这个接口返回的都是"error":"invalid_client",所以使用composer require lcobucci/jwt这个库,具体代码如下:
$payload = array(
"iss" => "Your Team ID",
"aud" => "https://appleid.apple.com",
"iat" => time(),
"sub" => "Your App Bundle ID",
"exp" => time()+ 86400*180
);
$jwt_header = array(
'typ' => 'JWT',
'alg' => 'ES256',
'kid' => 'The Key ID of the private key',
);
$key_path = 'file://D:\apple\AuthKey_keyid.p8';
$signer = new Lcobucci\JWT\Signer\Ecdsa\Sha256();
$key = new Lcobucci\JWT\Signer\Key($key_path);
$builder = new Lcobucci\JWT\Builder();
$builder->sign($signer, $key);
foreach($jwt_header as $key => $value)
$builder->withHeader($key, $value);
foreach($payload as $key => $value)
$builder->withClaim($key, $value);
$jwt_token = $builder->getToken();
// print_r($authorizationCode);
$jwt = (string)$jwt_token;
3.生成jwt格式的client_secret后,可以拿去JWT官网解析看看结果
4.生成和刷新token
(1)请求url为POST https://appleid.apple.com/auth/token
(2)生成令牌我们需要传以下几个参数
grant_type:'authorization_code'为获取令牌
client_id:client_id
redirect_uri:redirect_uri
code:上一步获取到的授权码,code
client_secret:一个生成的JWT,如果不了解可自行查阅有关JWT的知识
(3)刷新令牌我们需要传以下参数
grant_type:'refresh_token'为刷新令牌
client_id:client_id
client_secret:client_secret,
refresh_token:上一步获取到的id_token
具体代码如下:
$appleConfig = array();
$appleConfig['client_id'] = 'Your App Bundle ID';
$appleConfig['client_secret'] = $jwt;
$appleConfig['code'] = $authorizationCode;
$appleConfig['grant_type'] = 'authorization_code';//authorization_code,refresh_token
$biliConfig['redirect_uri'] = 'https://example.org';
// $appleConfig['refresh_token'] = 'rb65c3869af18460fb456fdgfh8.0.nrquq.DWHUDo7YTmZG_wqewwq-w';
$szUrl = 'https://appleid.apple.com/auth/token';
$request = new HttpHelper();
$response = $request->post($szUrl, $appleConfig);
5.响应结果
(1)生成token响应结果:
{"access_token":"xxxxxx","token_type":"Bearer","expires_in":3600,"refresh_token":"xxxxxx","id_token":"xxxxxxx"},其中id_token是一个JWT格式,所以需要再次解析。
(2)刷新token响应结果:
{"access_token":"xxxxxx","token_type":"Bearer","expires_in":3600}
注意:根据官方文档说明“You may verify the refresh token up to once a day to confirm that the user’s Apple ID on that device is still in good standing with Apple’s servers. Apple’s servers may throttle your call if you attempt to verify a user’s Apple ID more than once a day”,说的刷新token一天最多刷新一次,多了可能会限制你的账号,所以最终考虑不使用这个接口进行登录验证。
6.参考文档
(1)Generate and validate tokens
(2)Sign In With Apple 从登陆到服务器验证
(3)Sign in with Apple NODE,web端接入苹果第三方登录
(4)关于Sign in with Apple (Apple 登录) PHP的后端验证
(5)oauth2-apple
(6)what-the-heck-is-sign-in-with-apple
(7)sign-in-with-apple-example
(8)What are we supposed to do with the access_token
(9)Apple Sign-In: Custom Servers and an Expiry Conundrum
(10)快速配置 Sign In with Apple