现在Apple规定app必须支持删除账号的功能,而不能是简单的退出或者封禁账户。这是一个很好的举措,毕竟用户既然走到删除账户这一步,证明这个app并没有给用户带来理想的体验,所以也不希望预留个人信息在平台上。苹果额外规定如果使用AppleID登录,注销时也需要撤销AppleID的授权。

查看授权的路径

可以通过以下路径查看已授权AppleID登录的app:手机设置 》 Apple ID 》 密码与安全性 》 使用Apple ID的APP

撤销流程开始

一、获取撤销请求的token generate and validate tokens

1.1、接口地址

https://appleid.apple.com/auth/token

1.2、post请求,请求的Content-Typeapplication/x-www-form-urlencoded

1.3、请求参数

参数名参数值
client_idapp的bundle identifier
client_secret字符串,生成方式看下面1.4章节介绍
code字符串,APP端用户调用apple id登录授权时,在public func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization)回调函数中的authorization.credentialASAuthorizationAppleIDCredential类型,包含的authorizationCode值, 可以使用String(data: authorizationCode, encoding: .utf8)获得需要的值。这个值的有效期五分钟、并且是一次性的,所以如果用户注销的话,需要主动让用户再调用一次授权上传给服务器,以便请求撤销token
grant_type字符串,写死 authorization_code

其他参数是可选的,可以不用填写

1.4、client_secret生成

可以按照下面的操作步骤来生成client_secret,别漏掉咯

  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. 电脑安装Ruby的环境,mac默认已经安装,终端运行命令 sudo gem install jwt 来安装 ruby-jwt
  6. 新创建一个文本文件,secret_gen.rb文件,内容如下,修改一下里面的参数,对应的含义已经注释过
require "jwt"
key_file = "Path to the private key"    #刚刚下载的p8文件的本地路径
team_id = "Your Team ID"            #开发账号的team ID,在https://developer.apple.com/account/的Membership中查看
client_id = "The Service ID of the service you created"    #app的`bundle identifier`
key_id = "The Key ID of the private key"    #生成那个p8文件时的key id,在Certificates, Identifiers & Profiles > Keys点击生成的key中查看,默认就是那个p8文件名中的编号
validity_period = 180 # In days. Max 180 (6 months) according to Apple docs.

private_key = OpenSSL::PKey::EC.new IO.read key_file

token = JWT.encode(
   {
      iss: team_id,
      iat: Time.now.to_i,
      exp: Time.now.to_i + 86400 * validity_period,
      aud: "https://appleid.apple.com",
      sub: client_id
   },
   private_key,
   "ES256",
   header_fields=
   {
      kid: key_id 
   }
)
puts token

编辑保存之后,在终端运行这个文件ruby secret_gen.rb即可获得对应的client_secret

二、撤销token

上面第一步请求之后,会获取到对应用户的token,然后拿上一步的token去撤销AppleID授权

2.1、接口地址

https://appleid.apple.com/auth/token

2.2、post请求,请求的Content-Typeapplication/x-www-form-urlencoded

2.3、请求参数

参数名参数值
client_idapp的bundle identifier
client_secret第一步1.4章节生成的client_secret
token字符串,第一步请求拿到的token
token_type_hint字符串,写死 access_token

请求之后即可成功

三、验证

验证步骤很简单,撤销成功之后,在手机设置中查看使用Apple ID的APP,里面不再包含你的app,同时在你的app中重新请求AppleID登录时,也会重新弹出授权弹窗。这就证明之前的那个AppleID已经成功撤销了。

四、vapor的实现

vapor是一个swift开发的服务器框架,如果你服务器是用的这个,可以查看这个实现的demo,参数修改成你自己的app。其他框架根据上面实现的三步即可

4.1、token返回值

import Vapor

final class Cont_AppleToken: Content {
    var access_token: String?
    var token_type: String?
    var expires_in: Int?
    var refresh_token: String?
    var id_token: String?
}

4.2、请求撤销类

import Vapor

class AppleRevokeTool {
    //获取撤销请求的token
    func generateToken(_ req: Request, appleAuthorizationCode: String) throws -> EventLoopFuture<Cont_AppleToken> {
        return req.client.post("https://appleid.apple.com/auth/token") { tokenReq in
            // Encode JSON to the request body.
            try? tokenReq.content.encode(["client_id": "com.lazypig.cicada", "client_secret": AppleLoginClientSecret, "code": appleAuthorizationCode, "grant_type": "authorization_code"])
            tokenReq.headers.add(name: "Content-Type", value: "application/x-www-form-urlencoded")
        }.flatMapThrowing { res in
            try res.content.decode(Cont_AppleToken.self)
        }
    }

    //撤销token
    func revokeToken(_ req: Request, token: String) -> EventLoopFuture<HTTPStatus> {
        return req.client.post("https://appleid.apple.com/auth/revoke") { tokenReq in
            // Encode JSON to the request body.
            try? tokenReq.content.encode(["client_id": "com.lazypig.cicada", "client_secret": AppleLoginClientSecret, "token": token, "token_type_hint": "access_token"])
            tokenReq.headers.add(name: "Content-Type", value: "application/x-www-form-urlencoded")
        }.map { clientResponse in
            return clientResponse.status
        }
    }
}

4.3、请求撤销

//撤销apple ID的授权,appleAuthorizationCode为app上传上来的用户code
let revokeTool = AppleRevokeTool()
_ = try? revokeTool.generateToken(req, appleAuthorizationCode: appleAuthorizationCode).flatMap { cont_AppleToken -> EventLoopFuture<HTTPStatus> in
         if let token = cont_AppleToken.access_token {
                 return revokeTool.revokeToken(req, token: token).map({ status -> HTTPStatus in
                            return status
                  })
            }
          return req.eventLoop.future(HTTPStatus.ok)
 }

参考链接


☟☟可点击下方广告支持一下☟☟

Last modification:October 19, 2023
请我喝杯可乐,请随意打赏: ☞已打赏列表