# 使用 Apple 登录

**URL:** https://meta.discourse.org/t/sign-in-with-apple/122790
**Category:** Feature
**Created:** [2019年七月12日 12:38 UTC](https://meta.discourse.org/t/sign-in-with-apple/122790 "2019-07-12T12:38:45Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![stuartbreckenridge](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/stuartbreckenridge/32/149141_2.png) [@stuartbreckenridge](https://meta.discourse.org/u/stuartbreckenridge)
#### Post date: [2019年七月12日 12:38 UTC](https://meta.discourse.org/t/sign-in-with-apple/122790/1 "2019-07-12T12:38:45Z")

</div>

当“通过 Apple 登录”今年晚些时候正式向公众开放时，它是否会成为一种受支持的登录方式？

---

<div class="post-metadata">

### Author: ![eviltrout](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/eviltrout/32/5275_2.png) [@eviltrout](https://meta.discourse.org/u/eviltrout)
#### Post date: [2019年七月12日 14:20 UTC](https://meta.discourse.org/t/sign-in-with-apple/122790/2 "2019-07-12T14:20:22Z")

</div>

目前还没有人分配到此任务，但我怀疑如果他们获得足够的关注，这件事就会发生。即使我们不在 Discourse 核心中快速实现，社区中很可能也会有人创建一个插件。

---

<div class="post-metadata">

### Author: ![stuartbreckenridge](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/stuartbreckenridge/32/149141_2.png) [@stuartbreckenridge](https://meta.discourse.org/u/stuartbreckenridge)
#### Post date: [2019年七月12日 14:55 UTC](https://meta.discourse.org/t/sign-in-with-apple/122790/3 "2019-07-12T14:55:45Z")

</div>

太棒了。我还没看到其他地方提到过，所以想着提一下！

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [2019年七月12日 14:58 UTC](https://meta.discourse.org/t/sign-in-with-apple/122790/4 "2019-07-12T14:58:42Z")

</div>

> [@eviltrout](#):
>
> 社区里会有人创建一个插件的。

既然我刚为 Discord 插件提交了 PR，那我也来试试这个吧，能有多难呢？😉

此外，我认为支持一家更注重隐私的公司来管理身份至关重要，毕竟，呃，比起其他我们不便提及的公司，这家更值得信任。

---

<div class="post-metadata">

### Author: ![Falco](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/falco/32/179432_2.png) [@Falco](https://meta.discourse.org/u/Falco)
#### Post date: [2019年七月12日 15:04 UTC](https://meta.discourse.org/t/sign-in-with-apple/122790/5 "2019-07-12T15:04:30Z")

</div>

就这么做，@merefield！

既然已经有了 omniauth-apple 策略，这应该是可行的：[GitHub - nhosoya/omniauth-apple: OmniAuth strategy for Sign In with Apple · GitHub](https://github.com/nhosoya/omniauth-apple)

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [2019年七月12日 15:26 UTC](https://meta.discourse.org/t/sign-in-with-apple/122790/6 "2019-07-12T15:26:30Z")

</div>

非常有用的，谢谢 Rafael

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [2019年七月20日 20:07 UTC](https://meta.discourse.org/t/sign-in-with-apple/122790/7 "2019-07-20T20:07:49Z")

</div>

现在已经非常接近了，但遇到了一个棘手的问题：

OAuth 策略需要一个 `pem` 密钥文件（你可以从 Apple 那群好心人那里获取）。

当我尝试将其存储到 SiteSetting 中时，文本 somehow 被损坏了，导致私钥生成失败：

`::OpenSSL::PKey::EC.new(options.pem)`

```plaintext
# OpenSSL::PKey::ECError

## invalid curve name

```

我尝试用 `\n` 来转义换行符。

除非我们能以某种方式将文件内容存储到 SiteSetting 中，否则我看不出这如何能够部署。

---

<div class="post-metadata">

### Author: ![Stephen](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/stephen/32/95011_2.png) [@Stephen](https://meta.discourse.org/u/Stephen)
#### Post date: [2019年七月20日 20:11 UTC](https://meta.discourse.org/t/sign-in-with-apple/122790/8 "2019-07-20T20:11:46Z")

</div>

.pem 文件只是公钥，对吗？

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [2019年七月20日 20:12 UTC](https://meta.discourse.org/t/sign-in-with-apple/122790/9 "2019-07-20T20:12:45Z")

</div>

在这种情况下，它包含了私钥（显然其中还编码了其他内容）。

代码随后使用该私钥生成客户端密钥。

我已使用 PEM 文件对该库进行了测试，文件本身是有效的，但一旦将文件粘贴到 SiteSetting 中，它（也许可以预见地）会被微妙地修改。

**更新** ：看起来 SiteSettings 中将 `\n` 替换为了 `\\n`，因此或许可以在检索时搜索 `\\` 并将其减少一个。

看来我已经解决了这个问题，抱歉造成刷屏。

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [2019年八月2日 16:57 UTC](https://meta.discourse.org/t/sign-in-with-apple/122790/10 "2019-08-02T16:57:11Z")

</div>

更新：

我的插件似乎能部分运行，但在尝试使用我作为 Apple 开发者所设置的凭据进行身份验证时，目前收到了 Apple 返回的一个模糊错误：

“由于发生错误，您的请求无法完成。请稍后再试。”

可想而知，这并没有给我提供太多线索。

情况还稍微复杂一些，因为他们的授权方案与 OAuth 2.0 标准有很大不同。

遗憾的是，由于该功能尚处于预发布阶段，我暂时无法向 Apple 提交完整的 TSI 工单，但我会提交一个 Feedback Issue。

代码仓库地址如下：

> **[GitHub - discourse/discourse-apple-auth: Login to Discourse with your Apple ID](https://github.com/discourse/discourse-apple-auth)**
>
> Login to Discourse with your Apple ID

注意：请自行承担风险，尚未成功测试！

---

<div class="post-metadata">

### Author: ![Falco](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/falco/32/179432_2.png) [@Falco](https://meta.discourse.org/u/Falco)
#### Post date: [2019年八月2日 16:59 UTC](https://meta.discourse.org/t/sign-in-with-apple/122790/11 "2019-08-02T16:59:57Z")

</div>

也许我们可以为 `pem` 文件使用文件上传？它有多大？

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [2019年八月2日 17:01 UTC](https://meta.discourse.org/t/sign-in-with-apple/122790/12 "2019-08-02T17:01:22Z")

</div>

> [@Falco](#):
>
> 它有多大？

非常小 🙂

PEM“文件”（作为站点设置中的字符串）似乎处理正常，所以这似乎不再是问题了。

最初的错误已经消失。JWT 现在似乎也能正常处理它。

我的解决方法是将换行符替换为 符号，然后在传递给 JWT 函数时将 符号再替换回换行符。这不太规范，但有效。直接提供 ‘/’ 会出问题，因为 Ruby 的处理方式如此。（不过我承认，尽管没有抛出异常，这仍可能是一个潜在问题区域）

非常欢迎您使用您的 Apple 凭据来尝试一下。

我担心我的凭据配置有误。

您需要提供：

- 团队 ID（Team ID）
- 客户端 ID（Client ID）
- PEM
- 密钥 ID（Key ID）

在 Apple 网站上进行所有这些设置非常繁琐 🙂

---

<div class="post-metadata">

### Author: ![david](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/david/32/157490_2.png) [@david](https://meta.discourse.org/u/david)
#### Post date: [2019年八月2日 23:38 UTC](https://meta.discourse.org/t/sign-in-with-apple/122790/13 "2019-08-02T23:38:20Z")

</div>

@merefield 我已经在 [sandbox.dtaylor.uk](http://sandbox.dtaylor.uk) 上成功运行了 🎉

为了支持域名验证，我不得不对 [我们的 fork](https://github.com/discourse/discourse-sign-in-with-apple/commits/master) 做了一些改动。我还为站点设置添加了一些更具体的描述，并启用了 PEM 的多行支持。

看起来 omniauth-apple gem 目前（可能）还不支持传递任何用户信息……这对我们来说用处不大。看来 sign-in-with-apple 几乎 [符合](https://openid.net/2019/06/27/open-letter-from-the-openid-foundation-to-apple-regarding-sign-in-with-apple/) OpenID Connect 标准，因此我们或许可以重用该插件的一些功能。

关于设置凭据，我发现这篇（名字非常贴切）的博客文章比苹果的官方文档更有用：

> **[What the Heck is Sign In with Apple?](https://developer.okta.com/blog/2019/06/04/what-the-heck-is-sign-in-with-apple)**
>
> Sign In with Apple is based on OAuth 2.0 and OpenID Connect, and provides a privacy-friendly way for users to sign in to websites and apps

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [2019年八月3日 06:22 UTC](https://meta.discourse.org/t/sign-in-with-apple/122790/14 "2019-08-03T06:22:29Z")

</div>

> [@david](#):
>
> @merefield 我在 [sandbox.dtaylor.uk](http://sandbox.dtaylor.uk) 上已成功运行 🎉

> [@david](#):
>
> 我不得不在 [我们的 fork](https://github.com/discourse/discourse-sign-in-with-apple/commits/master) 中做了一些更改。

太棒了！啊，`textarea` 对我来说是新的。这巧妙地避免了我之前添加的“变通方法”。完美！早知道就好了！😅

我喜欢你添加的 txt 文件验证检查，真是个好主意。我之前是手动完成的，但这对于部署使用来说是个巨大的帮助。

> [@david](#):
>
> 关于设置凭据，我发现这篇（名字非常贴切的）博客文章比 Apple 的文档更有用：

是的，我也用了那篇。

遗憾的是，合并你的 fork 后，我仍然收到来自 Apple 端的相同错误，所以我怀疑我在凭据方面还在做一些愚蠢的事情。如果方便的话，我可能会通过私信联系你交换意见！😉

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [2019年八月3日 18:15 UTC](https://meta.discourse.org/t/sign-in-with-apple/122790/15 "2019-08-03T18:15:21Z")

</div>

好的，看来我的问题几乎可以肯定是因为尝试访问一个部分开发中的网站（尽管它通过 nginx 运行并使用了 HTTPS）。

我尝试了一个生产环境网站，结果成功了：🎉

但不幸的是，正如你所说，“Name”字段没有被返回，这应该是中间件的问题，对吧？看起来是 Apple 在授权过程中允许你这样做。

---

<div class="post-metadata">

### Author: ![Stephen](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/stephen/32/95011_2.png) [@Stephen](https://meta.discourse.org/u/Stephen)
#### Post date: [2019年八月3日 18:20 UTC](https://meta.discourse.org/t/sign-in-with-apple/122790/16 "2019-08-03T18:20:05Z")

</div>

我们确定它会返回一个名字吗？从隐私角度来看，由用户自行选择名字比在过程中泄露任何公开的个人身份信息要好得多。

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [2019年八月3日 18:36 UTC](https://meta.discourse.org/t/sign-in-with-apple/122790/17 "2019-08-03T18:36:05Z")

</div>

> [@Stephen，帖子：16，主题：122790](#):
>
> 我们确定它会返回一个名字吗？从隐私角度来看，不返回可能更好。

从技术上讲应该是这样的？不过我同意你的观点，尽管你可以在苹果页面上选择不公开它。事实证明，目前这已经无关紧要了！

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [2019年八月3日 21:09 UTC](https://meta.discourse.org/t/sign-in-with-apple/122790/18 "2019-08-03T21:09:28Z")

</div>

> [@david](#):
>
> 看起来 omniauth-apple 这个 gem 目前（还不？）支持传递任何用户信息……

是的，曾有人就此提出过问题，但随后被关闭了。

[我已在该问题上发表了评论](https://github.com/nhosoya/omniauth-apple/issues/8)

我猜我们关注的代码区域应该是 [这里](https://github.com/nhosoya/omniauth-apple/blob/master/lib/omniauth/strategies/apple.rb)：

```plaintext
      info do
        { sub: id_token['sub'] }
      end

```

而在 discord auth gem 中，例如，我们得到的是 [这个](https://github.com/adaoraul/omniauth-discord/blob/master/lib/omniauth/strategies/discord.rb)：

```plaintext
      info do
        {
          name: raw_info['username'],
          email: raw_info['verified'] ? raw_info['email'] : nil,
          image: "https://cdn.discordapp.com/avatars/#{raw_info['id']}/#{raw_info['avatar']}"
        }
      end

```

附注：Apple 的 API 文档中并未提及这些字段……

> **[TokenResponse | Apple Developer Documentation](https://developer.apple.com/documentation/signinwithapplerestapi/tokenresponse)**
>
> The response token object returned on a successful request.

---

<div class="post-metadata">

### Author: ![david](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/david/32/157490_2.png) [@david](https://meta.discourse.org/u/david)
#### Post date: [2019年八月5日 10:13 UTC](https://meta.discourse.org/t/sign-in-with-apple/122790/19 "2019-08-05T10:13:28Z")

</div>

看起来这个 PR 添加了有用的用户信息：[https://github.com/nhosoya/omniauth-apple/pull/7。希望它能很快被合并，否则我们可以考虑使用一个](https://github.com/nhosoya/omniauth-apple/pull/7%E3%80%82%E5%B8%8C%E6%9C%9B%E5%AE%83%E8%83%BD%E5%BE%88%E5%BF%AB%E8%A2%AB%E5%90%88%E5%B9%B6%EF%BC%8C%E5%90%A6%E5%88%99%E6%88%91%E4%BB%AC%E5%8F%AF%E4%BB%A5%E8%80%83%E8%99%91%E4%BD%BF%E7%94%A8%E4%B8%80%E4%B8%AA) fork。

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [2019年八月5日 10:16 UTC](https://meta.discourse.org/t/sign-in-with-apple/122790/20 "2019-08-05T10:16:25Z")

</div>

是的，你说得对。我确实看到了那个 PR，但没有深入代码，以为只是切换了不同的依赖。大家提交 PR 时应该避免范围过大，否则像这样的细节容易被忽略。

正如你所说：

```plaintext
        {
          sub: id_info['sub'],
          email: user_info.dig('email'),
          first_name: user_info.dig('name', 'firstName'),
          last_name: user_info.dig('name', 'lastName'),
          extra: {
            raw_info: id_info.merge(user_info)
          }
        } 

```

我已在该 PR 下添加了评论表示支持。

[下一頁](https://meta.discourse.org/t/sign-in-with-apple/122790.md?page=2)
