使用苹果登录 - 验证后续调用而不显示登录 UI(刷新身份验证令牌)

Mos*_*ieb 7 ios apple-sign-in

每当我启动我的应用程序时,我都想确保苹果登录仍然有效,但我也希望能够向我的服务器证明这一点。
成功登录后,我可以ASAuthorizationAppleIDProvider.getCredentialState用来确定我的凭据对于后续登录是否仍然有效。
这工作正常,但无法向我的服务器证明此过程已成功执行,任何使用我的服务器 API 的人都可以告诉服务器不要担心,服务器将无法判断它是否是真正的客户端或不。
服务器还可以使用刷新令牌来验证用户是否仍然有效,方法是发出一个新的访问令牌(Apple 说每天不超过一次,但现在可以),但这也无济于事,因为我不希望密钥出现在客户端应用程序中,此外,即使我从客户端获得了一个新的访问令牌 - 服务器暂时无法使用它,因为当前不存在 API任何带有访问令牌的东西

我需要的是一个新的身份验证令牌,但是 - 当ASAuthorizationController.performRequests()使用 Apple ID 请求调用时 - 用户界面再次显示,而不仅仅是ASAuthorizationControllerDelegate使用新的授权令牌调用。
我还尝试refresh在第二次登录尝试中将请求操作设置为:

    let request = appleIDProvider.createRequest()
    request.requestedOperation = .operationRefresh
Run Code Online (Sandbox Code Playgroud)

同样的结果,UI 仍然显示。
有没有办法在不显示 UI 的情况下使用 Apple ID 重新进行身份验证,并获得某种令牌,服务器可以使用该令牌来验证登录的真实性?
请不要建议超出范围的方法,例如在向服务器初始证明后涉及我自己的登录机制并让服务器从那时起使用刷新令牌的方法 - 我可以自己提出这些解决方案- 我正在寻找苹果登录方法解决方案。

Dev*_*B2F 3

根据文档

\n\n
\n

验证身份令牌后,您的应用程序负责管理用户会话。您可以将会话\xe2\x80\x99s 生命周期与 Apple 设备上\n 成功的 getCredentialState(forUserID:completion:) 调用联系起来。这是一种本地、廉价、非网络调用,由 Apple ID 系统启用,使设备上的 Apple ID 状态与 Apple 服务器保持同步。

\n\n

每当请求新的身份令牌时都需要用户交互。用户会话在设备上的生命周期很长,因此在每次启动时\n 或每天一次以上\n 调用新的身份令牌可能会导致您的请求因限制而失败

\n\n

如果系统中的用户\xe2\x80\x99s Apple ID 发生更改,则调用 getCredentialState(forUserID:completion:) 表明用户已更改。假设其他用户已登录并注销\n app\xe2\x80\x99s 当前已知的用户。

\n\n

对于在其他系统上运行的应用,请使用刷新令牌的定期成功验证来确定用户会话的生命周期。

\n
\n\n

因此,这基本上意味着您应该在从 getCredentialState 获取结果时检查 userIdentifier 并确保它与当前用户的值相同。\n如果您想,您无法避免问题中提到的用户交互在应用程序中重新进行身份验证。

\n\n

首先,您必须从应用程序登录中获取用户标识符和授权代码并将其发送到您的服务器。还要创建一个长会话 ID 并将其也发送到您的服务器:

\n\n
if let appleIDCredential = authorization.credential as? ASAuthorizationAppleIDCredential {\n\n        let userIdentifier = appleIDCredential.user\n        print("userIdentifier: \\(userIdentifier)")\n\n        let authorizationCode = String(data: appleIDCredential.authorizationCode!, encoding: .utf8)!\n        print("authorizationCode: \\(authorizationCode)")  \n\n        let sessionID = veryLongToken\n\n        //send authorizationCode, userIdentifier and sessionId to server\n    }\n
Run Code Online (Sandbox Code Playgroud)\n\n

在您的服务器上,您在调用时获得identityToken:appleid.apple.com/token/auth

\n\n

和:

\n\n
#create token\nimport jwt  # pip install pyjwt\nclaims = {\n    \'iss\': teamID,\n    \'iat\': timeNow,\n    \'exp\': time3Months,\n    \'aud\': \'https://appleid.apple.com\',\n    \'sub\': app_id,\n}\nclient_secret = jwt.encode(claims, private_key_from_developer_portal, algorithm=\'ES256\', headers={\'kid\': kid})\n\n\ndata = {\n    \'client_id\': app_id,\n    \'client_secret\': client_secret,\n    \'grant_type\': grant_type,\n    \'redirect_uri\': redirect_uri,\n    \'code\': authorizationCode,\n}\n\nheaders = {\n    \'Content-Type\': \'application/x-www-form-urlencoded\',\n}\n\nresponse = requests.request(\n    method=\'POST\',\n    url=\'https://appleid.apple.com/auth/token\',\n    data=data,\n    headers=headers,\n)\n#response will include refresh_token, access_token and id_token\n
Run Code Online (Sandbox Code Playgroud)\n\n

您现在可以从 id_token 检索用户电子邮件和 userIdentifier:

\n\n
result = jwt.decode(id_token, verify=False)\nprint("jwtResult: " + result)\n\nuserIdentifier = result["sub"]\nemail = result["email"]\n
Run Code Online (Sandbox Code Playgroud)\n\n

现在你从苹果知道它是什么用户了。根据\n验证令牌文档,您首先使用 grant_type 中的authorization_code 来获取refresh_token,然后使用refresh_token 作为 grant_type

\n\n

这是验证用户是否仍在服务器上进行身份验证的唯一方法。

\n\n

因此,将 sessionId 以及有关 Apple 登录(刷新令牌...)的一些信息存储在您的服务器上。

\n\n

您可以让应用程序在需要来自服务器的数据时将 sessionId 发送到服务器,并且在将某些信息移交给应用程序之前,在服务器上执行刷新令牌验证。如果身份验证无效,则应用程序应删除 sessionId 并注销。

\n\n

这是您能够在服务器上验证身份验证是否有效的唯一方法。

\n\n

通过阅读文档,这似乎是推荐的方式,您尝试做的事情将会导致问题,并且苹果不希望您始终在应用程序中对用户进行身份验证。

\n\n

您还应该查看 Apple 的这个示例项目,以使用 Apple 登录。

\n\n

果汁示例项目

\n

  • 谢谢!虽然它并没有真正回答我的问题(在后续请求中向服务器提供证据)-它基本上涵盖了我已经收集到的内容:没有办法做到这一点,并且一旦经过身份验证,我需要使用我自己的身份验证方案到这一点(长时间运行的会话只是一个示例),当然,运行客户端测试以撤销登录和定期服务器令牌刷新。 (5认同)