使用 Apple 登录

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

16 个赞

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

12 个赞

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

既然我刚为 Discord 插件提交了 PR,那我也来试试这个吧,能有多难呢?:wink:

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

13 个赞

就这么做,@merefield

既然已经有了 omniauth-apple 策略,这应该是可行的:GitHub - nhosoya/omniauth-apple: OmniAuth strategy for Sign In with Apple · GitHub

16 个赞

非常有用的,谢谢 Rafael

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

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

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

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

# OpenSSL::PKey::ECError

## invalid curve name

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

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

1 个赞

.pem 文件只是公钥,对吗?

在这种情况下,它包含了私钥(显然其中还编码了其他内容)。

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

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

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

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

7 个赞

更新:

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

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

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

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

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

代码仓库地址如下:

注意:请自行承担风险,尚未成功测试!

7 个赞

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

非常小 :slight_smile:

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

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

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

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

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

您需要提供:

  • 团队 ID(Team ID)
  • 客户端 ID(Client ID)
  • PEM
  • 密钥 ID(Key ID)

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

8 个赞

@merefield 我已经在 sandbox.dtaylor.uk 上成功运行了 :tada:

为了支持域名验证,我不得不对 我们的 fork 做了一些改动。我还为站点设置添加了一些更具体的描述,并启用了 PEM 的多行支持。

看起来 omniauth-apple gem 目前(可能)还不支持传递任何用户信息……这对我们来说用处不大。看来 sign-in-with-apple 几乎 符合 OpenID Connect 标准,因此我们或许可以重用该插件的一些功能。

关于设置凭据,我发现这篇(名字非常贴切)的博客文章比苹果的官方文档更有用:

11 个赞

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

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

是的,我也用了那篇。

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

7 个赞

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

我尝试了一个生产环境网站,结果成功了::tada:

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

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

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

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

我已在该问题上发表了评论

我猜我们关注的代码区域应该是 这里

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

而在 discord auth gem 中,例如,我们得到的是 这个

      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 文档中并未提及这些字段……

看起来这个 PR 添加了有用的用户信息:https://github.com/nhosoya/omniauth-apple/pull/7。希望它能很快被合并,否则我们可以考虑使用一个 fork。

5 个赞

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

正如你所说:

        {
          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 下添加了评论表示支持。

4 个赞