Apple 登录:如何将其用于自定义服务器端点身份验证? [英] Apple Sign-In: How to use it for custom server endpoint authentication?

查看:83
本文介绍了Apple 登录:如何将其用于自定义服务器端点身份验证?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的用例是,一旦我有用户登录我的应用程序,当我从我的应用程序向我的自定义服务器进行端点调用时,我使用由登录产生的 Oauth 令牌来验证调用者.例如,我以这种方式使用 Google 登录.

此方法(例如,使用 Google Sign In)有几个有用的属性:

  1. 更新的令牌会在客户端应用上自动创建.

  2. 我的自定义服务器可以使用 Google 的端点轻松验证令牌的有效性.

  3. 初始令牌验证可以在端点请求处理的早期进行——无需访问自定义服务器数据库(如 https://github.com/IBM-Swift/Kitura-Credentials).

我的问题是:鉴于我们被告知必须将 Apple Sign-In 合并到我们的 iOS 应用程序中(如果我们提供通用登录设施),我该如何做端点使用我的自定义服务器进行身份验证?

我看到了两种选择,但我都不喜欢.

首先,我可以让我的客户端应用程序向我的服务器发送一个 Apple 登录 id_token 并忽略 exp(到期)字段.我可以定期重新生成 id_token(显然,每天不超过一次)并发送它返回给我的客户.我不喜欢这个想法,因为忽略了令牌的到期时间,并且因为需要定期将令牌从服务器发送到客户端.(我的应用使用多登录系统,这只会增加额外的难度).

第二,我可以让我的客户发送一个 Apple 登录刷新令牌到我的服务器.当然,我的服务器首先需要生成刷新令牌并将其发送回客户端.我比第一个想法更不喜欢这个想法.我在自定义服务器中的初始令牌验证将需要访问其数据库以查找匹配此令牌.我通常不能使用 Apple 端点——因为 Apple 显然会再次限制这种验证.

此外,我真的不喜欢我的自定义服务器最多可以每天检查一次令牌有效性的想法.如果用户撤销应用的凭据,我希望我的自定义服务器能够相对较快地停止代表用户进行操作.

想法?


10/5/19-- 更新到上面的第一个选项.实际使用https://developer.apple.com/documentation/signinwithapplerestapi/generate_and_validate_tokens 对于刷新令牌验证,我发现它实际上并未生成更新的 id 令牌.它正在生成一个访问令牌(但 Apple 没有定义它的用途),并且正在验证刷新令牌.因此,无法将更新的 id 令牌发送到客户端 iOS 应用程序.因此,使用第一种方法时,无法使用 id 令牌的到期日期.

10/10/19-- 更新:我写了一篇关于这个主题的博客文章-- https://medium.com/@crspybits/apple-sign-in-custom-servers-and-an-expiry-conundrum-d1ad63223870

8/6/20-- 更新:关注博客文章,了解可能的前进方向,Apple 未决详细信息:https://medium.com/@crspybits/part-ii-apple-sign-in-custom-servers-and-an-expiry-conundrum-b3e9735dc079

解决方案

获取在 WWDC 2020 中使用 Apple 登录的最佳体验,在 11:30 的演示中,他们引入了服务器到服务器的通知,使您的服务器能够实时监控用户帐户状态的变化.

到目前为止,关于这方面的细节很少.

----------------- 更新 (12/23/20) -----------------

我现在在我的服务器的测试环境中使用这些服务器到服务器的通知.一些注意事项:

  1. 我决定在我的服务器上使用端点,以允许 Apple 向我的服务器发送这些 REST 端点请求.

  2. 我把它粘贴到 developer.apple.com >帐户 >证书、标识符和配置文件 >标识符 >选择您的应用标识符 >单击使用 Apple 登录"旁边的编辑">服务器到服务器通知端点

  3. 这个端点实际上是未经授权的.例如,它是由 Apple 制作的,没有对您的服务器的 OAuth 凭据访问.如何设置取决于您的服务器.我有办法为我的服务器设置一个未经授权的新端点/路由.

  4. 我已将客户端和服务器的其他部分设置为允许使用 Apple 登录创建帐户.因此,使用这些帐户之一,我现在开始采取行动,导致 Apple 在我的服务器上调用他们的服务器到服务器通知端点.我想对 Apple 提出的端点请求的细节进行逆向工程,因为细节很少.这提供了一些关于如何导致通知事件发生的想法:如何撤销使用 Apple 凭据登录对于特定应用?您可以撤销凭据,但启用和禁用电子邮件中继更容易(因为您可以重复执行此操作).当然,要做到这一点,您必须首先使用私人/电子邮件中继登录 Apple.

  5. 接下来我学到了两件事:

a) 在您采取行动(例如,撤销电子邮件中继)后,大约 30 秒内将在您的服务器上访问服务器到服务器的通知端点.我已经在我的服务器中添加了各种日志输出,所以可以查看我的服务器日志并看到这种情况发生.

b) Apple 向您的服务器发出的端点请求具有包含以下格式的 JSON 的正文数据:<代码>{有效载荷": "-- SNIP -- JWT"}

我正在使用以下 Swift 结构对其进行解码.

 struct ApplePayload:可解码{让有效负载:字符串//JWT}

  1. 正如 Apple 在 WWDC 2020 视频中指出的那样 (https://developer.apple.com/videos/play/wwdc2020/10173/),body数据的主要内容是一个JWT.上面,这是密钥payload"的值.在 JSON 中.

  2. 下一步是解码这个 JWT.我只是猜测它会使用与 Apple 登录服务器端流程的其他部分中的 JWT 相同的解码机制.特别是,在解码由客户端使用 Apple 登录传递给您的服务器的身份令牌(JWT)时.请参阅 https://developer.apple.com/documentation/sign_in_with_apple/sign_in_with_apple_rest_api/authenticating_users_with_sign_in_with_apple我有一些代码可以进行 JWT 解码,因此我将其分解并将其放在一个公共位置:https://github.com/SyncServerII/AppleJWTDecoder.git将它集成到我对 Apple 的服务器到服务器通知请求的服务器端处理中,我发现这个 JWT 确实可以用这种方式解码.

  3. 另一个显而易见的方面是,Apple 在 WWDC 2020 视频中指出的结构在解码后并非 100% 出现在 JWT 中.具体来说,到目前为止,在我的测试中,至少 events 字段不是数组,而是具有单个值.请参阅 https://github.com/SyncServerII/AppleJWTDecoder/blob/main/Sources/AppleJWTDecoder/AppleSignInClaims.swift 用于 Swift 结构.

我现在成功解析了 JWT.我服务器上的下一个主要步骤是实际利用我服务器中的不同事件类型来采取行动.对我来说,这将涉及两个帐户(不是电子邮件)相关的操作:

<块引用>

用户决定停止在您的应用程序中使用他们的 Apple Id.和应被视为用户退出.例如,当用户决定断开您的应用程序与设置的连接.(从https://developer.apple.com/videos/play/wwdc2020/10173/)

还考虑了用户删除其应用帐户"的请求;(更广泛的上下文:服务器到服务器通知端点登录苹果服务器到服务器通知让你接收重要的有关您的用户及其帐户的更新.通知已发送对于用户更改邮件转发首选项时的每个应用程序组,删除他们的应用程序帐户,或永久删除他们的 Apple ID.每个一组应用程序可以有一个 URL,该 URL 必须是绝对的,并且包括方案、主机和路径.需要 TLS 1.2 或更高版本才能接收通知.了解更多.")要查看这些文档,请访问:developer.apple.com >帐户 >证书、标识符和配置文件 >标识符 >选择您的应用标识符 >单击签名"旁边的编辑"在与 Apple >服务器到服务器通知端点

caseconsentRevoked =同意撤销";

<块引用>

用户已要求 Apple 删除其 Apple Id.用户标识符现在将不再有效.

case accountDelete = "account-delete";

我的计划是将这两个事件等同起来 - 并删除我服务器上的用户帐户.然后我将不得不考虑如何将其传达给我的客户(iOS 应用程序).它需要知道用户已经删除了他们的帐户.

My use case is that once I have a user signed into my app, I use the Oauth token, resulting from the sign-in, when I make endpoint calls from my app to my custom server-- to authenticate the caller. E.g., I use Google Sign In in this way.

This method (e.g., with Google Sign In) has several useful properties:

  1. Updated tokens are created automatically on the client app.

  2. My custom server can easily verify the validity of the token, using Google's endpoints.

  3. Initial token verification can take place early in the endpoint request processing-- without access to the custom servers database (as in the style in https://github.com/IBM-Swift/Kitura-Credentials).

My question is: Given that we're being told we have to incorporate Apple Sign-In into our iOS apps (if we offer general purpose sign-in facilities), how can I do endpoint authentication with my custom server?

I see two alternatives, neither of which I like very much.

First, I can have my client app send an Apple Sign In id_token to my server and ignore the exp (expiry) field. I can regenerate the id_token periodically (apparently, no more than once a day) and send it back to my client. I don't like this idea both because of ignoring the expiry of the token, and because of the need to periodically send the token from server to client. (My app uses multiple sign in systems and this just creates extra difficulty).

Second, I could have my client send an Apple Sign In refresh token to my server. My server would need, of course, to initially generate that refresh token and send it back to the client. I like this idea even less than the first idea. My initial token verification in my custom server would need to access its database to look for a match this token. I can't generally use an Apple endpoint -- because, again, Apple is apparently going to throttle this verification.

Additionally, I don't really like the idea that my custom server can, at best, check on token validity once a day. If the user revokes the app's credentials, I would hope my custom sever would stop being able to operate on behalf of the user relatively quickly.

Thoughts?


10/5/19-- update to the first alternative above. Upon actual use of https://developer.apple.com/documentation/signinwithapplerestapi/generate_and_validate_tokens for refresh token validation, I find that it is not actually generating an updated id token. It is generating an access token (but Apple doesn't define a use for that), and is validating the refresh token. And so, there is no way to send an updated id token to the client iOS app. Thus, using the first alternative, the expiry date of the id token cannot be used.

10/10/19-- update: I've written a blog article on this subject-- https://medium.com/@crspybits/apple-sign-in-custom-servers-and-an-expiry-conundrum-d1ad63223870

8/6/20-- update: Follow on blog article with possible path forward, pending details from Apple: https://medium.com/@crspybits/part-ii-apple-sign-in-custom-servers-and-an-expiry-conundrum-b3e9735dc079

解决方案

In Get the most out of Sign in with Apple in WWDC 2020, at 11:30 in their presentation, they introduce server-to-server notifications to enable your server to monitor user account state changes on a real-time basis.

So far, few details on this though.

----------------- UPDATE (12/23/20) -----------------

I now have these server-to-server notifications working in a testing environment with my server. Some notes:

  1. I decided on the endpoint to use, on my server, to allow Apple to send my server these REST endpoint requests.

  2. I pasted that into developer.apple.com > Account > Certificates, Identifiers & Profiles > Identifiers > Select your app identifier > Click 'Edit' next to 'Sign In with Apple' > Server to Server Notification Endpoint

  3. This endpoint is effectively unauthorized. E.g., it is made by Apple with no OAuth credential access to your server. How this is setup will depend on your server. I had a means to set up a new endpoint/route for my server that was unauthorized.

  4. I have the client side and other parts of my server set up to allow creation of accounts using Apple Sign In. So, using one of those accounts, I now started taking actions that would cause Apple to invoke their server-to-server notification endpoint on my server. I wanted to reverse engineer the details of the endpoint request Apple is making, since details are scarce. This provides some ideas on how to cause the notification events to occur: How to revoke Sign in with Apple credentials for a specific app? You can revoke credentials, but it's easier (because you can do it repeatedly) to enable and disable the email relay. Of course, to do this, you have to initially sign-in with Apple using the private/email relay.

  5. I next learned two things:

a) After you take the action (e.g., revoke the email relay), the server-to-server notification endpoint is accessed on your server within about 30 seconds. I had added various log output into my server, so could watch my server log and see this happening.

b) The endpoint request Apple makes to your server has body data containing JSON in the following format: {"payload" : "-- SNIP -- JWT"}

I'm using the following Swift structure to decode this.

    struct ApplePayload: Decodable {
        let payload: String // JWT
    }

  1. As Apple has indicated in the WWDC 2020 video (https://developer.apple.com/videos/play/wwdc2020/10173/), the main content of the body data is a JWT. Above, this is the value of the key "payload" in the JSON.

  2. The next step is decoding this JWT. I just guessed that it would use the same mechanism for decoding as with the JWT in other parts of the Apple Sign In server-side process. And specifically, in decoding the identity token (a JWT) passed up to your server by a client using Apple sign in. See https://developer.apple.com/documentation/sign_in_with_apple/sign_in_with_apple_rest_api/authenticating_users_with_sign_in_with_apple I had some code that did this JWT decoding, so I factored that out and put it in a common place: https://github.com/SyncServerII/AppleJWTDecoder.git Integrating that into my server-side processing of Apple's server-to-server notification requests, I found that indeed this JWT can be decoded in this manner.

  3. Another aspect that became evident is that the structure indicated by Apple in the WWDC 2020 video isn't 100% what is present in the JWT, after decoding. Specifically, in my tests so far at least the events field is not an array, rather it has a single value. See https://github.com/SyncServerII/AppleJWTDecoder/blob/main/Sources/AppleJWTDecoder/AppleSignInClaims.swift for a Swift structure.

I am now successfully parsing the JWT. The next main step on my server is to actually utilize the different event types in my server to take actions. For me this is going to involve the two account (not email) related actions:

User decided to stop using their Apple Id with your application. And should be treated as a sign-out by the user. E.g., when a user decides to disconnect your application from Settings. (From https://developer.apple.com/videos/play/wwdc2020/10173/)

Also considered a request from user to "delete their app account" (broader context: "Server to Server Notification Endpoint Sign in with Apple server to server notifications allow you to receive important updates about your users and their accounts. Notifications are sent for each app group when users change mail forwarding preferences, delete their app account, or permanently delete their Apple ID. Each group of apps can have one URL, which must be absolute and include the scheme, host, and path. TLS 1.2 or higher is required to receive notifications. Learn more.") To see these docs, go to: developer.apple.com > Account > Certificates, Identifiers & Profiles > Identifiers > Select your app identifier > Click 'Edit' next to 'Sign In with Apple' > Server to Server Notification Endpoint

case consentRevoked = "consent-revoked"

    

User has asked Apple to delete their Apple Id. The user identifier will now no longer be valid.

case accountDelete = "account-delete"

My plan is to take both of these events as equivalent- and delete the user's account on my server. I'm then going to have to consider how to communicate this to my client (iOS app). It will need to know that the user has deleted their account.

这篇关于Apple 登录:如何将其用于自定义服务器端点身份验证?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆