apple登录服务端验证

Sign In With Apple 从登陆到服务器验证

  • 服务端向苹果请求验证
    手机端需要提交 user 、authorizationCode 、 identityToken 字段信息(code和token字段苹果返回的是 base64 Data 形式,手机端可以先转换 base64 字符串之后在给服务器)到服务器。然后服务器通过 https://appleid.apple.com/auth/token 该接口,并拼接对应参数去验证,接口相关信息苹果有提供 Generate and validate tokens 。参考链接:https://developer.apple.com/documentation/sign_in_with_apple/generate_and_validate_tokens
    下面着重介绍几个参数及其获取方法。首先先看下该接口需要的参数,如下:

    client_id: string (Required) (Authorization and Validation) The application identifier for your app
    
    client_secret: string (Required) (Authorization and Validation) A secret generated as a JSON Web Token that uses the secret key generated by the WWDR portal.
    
    code: string (Authorization) The authorization code received from your application’s user agent. The code is single use only and valid for five minutes.
    
    grant_type: string (Required) (Authorization and Validation) The grant type that determines how the client interacts with the server. For authorization code validation, use authorization_code. For refresh token validation requests, use refresh_token.
    
    refresh_token: string (Validation) The refresh token received during the authorization request.
    
    redirect_uri: string (Authorization) The destination URI the code was originally sent to.
    

    其中 client_id 为app的 bundle identifier , code 即为手机端获取到的 authorizationCode 信息, grant_type 传入固定字符串 authorization_code 即可。还剩下一个必要参数 client_secret 那么这个参数相对麻烦点,需要我们自己生成。client_secret参数是一个JWT,singature部分使用非对称加密 RSASSA【RSA签名算法】 和 ECDSA【椭圆曲线数据签名算法】。
    生成 client_secret 之前,我们需要做如下工作

    • 获取 APP 的 bundleID
    • 获取开发者账号的TeamID
      在这里插入图片描述
    • 创建 privateKey,获取到 Key ID 和 私钥
      在这里插入图片描述
      创建完之后把私钥下载下来,并保存好,注意,私钥只能下载一次。
  • 生成client_secret

    {
    //首先composer编译加载"lcobucci/jwt": "^3.4"
    "require": {
        "facebook/graph-sdk": "^5.7", //facebook
        "lcobucci/jwt": "^3.4"//apple
    }
    //然后拼凑参数生成jwt格式密钥
    $payload = array(
    	"iss" => 'XXXX',//开发者账号的TeamID
    	"aud" => "https://appleid.apple.com",
    	"iat" => time(),
    	"sub" => 'XXXX',//bundle id
    	"exp" => time()+ 86400*180
    
    );
    
    $jwt_header = array(
    	'typ' => 'JWT',
    	'alg' => 'ES256',
    	'kid' => 'XXXX',//上面截图的keyId
    );
    
    $key_path = 'XXXX';//下载的私钥文件,此文件为.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();
    $jwt = (string)$jwt_token;//此jwt就为生成的client_secret
    
    //接下来就是拼凑请求参数
    $appleConfig = array();
    $appleConfig['client_id'] = 'XXXX;//bundle id
    $appleConfig['client_secret'] = $jwt;
    $appleConfig['code'] = $authorizationCode;//客户端获取的code
    $appleConfig['grant_type'] = 'authorization_code';//authorization_code,refresh_token
    $szUrl = 'https://appleid.apple.com/auth/token';
    $headers[]  =  "Content-Type:application/x-www-form-urlencoded";//设置请求头
    $curl = curl_init();
    //设置抓取的url
    curl_setopt($curl, CURLOPT_URL, $szUrl);
    //设置头文件的信息作为数据流输出
    curl_setopt($curl, CURLOPT_HEADER,0);
    //设置请求头
    curl_setopt($curl, CURLOPT_HTTPHEADER,$headers);
    //设置获取的信息以文件流的形式返回,而不是直接输出。
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    //设置post方式提交
    curl_setopt($curl, CURLOPT_POST, 1);
    //设置post数据
    $post_data = urldecode(http_build_query($appleConfig));
    curl_setopt($curl, CURLOPT_POSTFIELDS, $post_data);
    //执行命令
    $response = curl_exec($curl);
    //关闭URL请求
    curl_close($curl);
    //返回结果
    $response = json_decode($response,true);
    
  • 返回结果如下

    {
      "access_token": "一个token,此处省略",
      "token_type": "Bearer",
      "expires_in": 3600,
      "refresh_token": "一个token,此处省略",
      "id_token": "结果是JWT,字符串形式,此处省略"
     }
    

    参数解释看这个文档:https://developer.apple.com/documentation/sign_in_with_apple/tokenresponse

  • 服务器拿到相应结果,其中 id_token 也是 JWT 数据,decode 出 payload 部分如下
    在这里插入图片描述
    其中 aud 部分与你的app的bundleID一致, sub 部分即与手机端获得的 user 一致,服务器端通过对比 sub 字段信息是否与手机端上传的 user 信息一致来确定是否成功登录。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值