使用 Apple 登录(iOS 应用 + 后端验证)API 返回错误“invalid_client"; [英] Sign in with Apple (iOS App + Backend verification) API returns error "invalid_client"

查看:64
本文介绍了使用 Apple 登录(iOS 应用 + 后端验证)API 返回错误“invalid_client";的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 iOS 应用和后端实现 Sign In with Apple.目标是这样的:

  1. 用户在 iOS 应用上登录
  2. 在得到肯定响应后,应用调用后端的端点并移交 authorizationCode
  3. 后端现在需要通过另一个对苹果服务器的调用来验证 authorizationCode.

在这里我很困惑.为了进行这个调用,后端需要提供一堆参数:

网址

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

查询参数

client_id = com.mycompany.appname客户秘密 = ...code = ...//`authorizationCode` 来自 iOS 应用中的登录grant_type = 授权码

我已经为 client_secret 生成了一个 JWT:

JWT 属性

标题:Kid:<key id,在 Apple Dev Portal 上创建>声称:iss: <团队ID>iat: <当前时间戳>exp: <当前时间戳 + 180 天>aud:https://appleid.apple.com"子:com.mycompany.appname"

昨天我在 Dev Portal 上为两个应用程序(A 和 B)创建了两个密钥,用它来生成秘密,今天应用程序 A 工作了,我得到了肯定的回应:

积极响应

<代码>{access_token":a1e64327924yt49f5937d643e25a48b81.0.mxwz.GN9TjJIJ5_4dR6WjbZoVNw","token_type" : "承载者",expires_in":3600,刷新令牌":rca76d9ebta644fde9edba269c61eeb41.0.mxwz.sMDUlXnnLLUOu2z0WlABoQ",id_token": eyJraWQiOiJBSURPUEsxIcccYWxnIjoiUlMyNTYifQ.eyJpc3MiOiJodHRwczovL2FwcGxlaWQuYXBwbGUuY29tIiwiYXVkIjoiZGUudHJ1ZmZscy5hcHBsZS1zaWduaW4tdGVzdCIsImV4cCI6MTU2NzcwMDI0MiwiaWF0IjoxNTY3Njk5NjQyLCJzdWaaaiIwMDA3NjkuYWY3NDdjMTlmZGRmNDJhNjhhYmFkZjhlNTQ1MmY3NjAuMjIwNSIsImF0X2hhc2giOiJrVThQTkZOUHYxS0RGUEtMT2hIY213IiwiYXV0aF90aW1lIjoxNTY3Njk5NjM5fQ.g3JD2MDGZ6wiVS9VMHpj24ER0XqJlunatmqpE7sRarMkhMHMTk7j8gty1lpqVBC6Z8L5CZuewdzLuJ5Odrd3_c1cX7gparTQE4jCyvyTACCPKHXReTC2hGRIEnAogcxv6HDWrtZgb3ENhoGhZW778d70DUdd-e4KKiAvzLOse-endHr51PaR1gv-cHPcwnm3NQZ144I-xhpU5TD9VQJ9IgLQvZGZ8fi8SOcu6rrk5ZOr0mpt0NbJNGYgH5-8iuSxo18QBWZDXoEGNsa4kS5GDkq5Cekxt7JsJFc_L1Np94giXhpbYHqhcO1pZSGFrJVaMvMMftZfuS_T3sh2yCqkcA"}

但是,B 仍然不起作用.今天我撤销了 A 的密钥并创建了一个新的,现在它不再适用于新的,但仍然适用于旧的,即使我在 Dev Portal 上删除了它.我很困惑.

响应错误:

<代码>{错误":无效客户端"}

我想知道 Apple 是否需要一些时间索引或类似的东西.我只是想了解它是如何工作的.

解决方案

可能发生的原因有几个:

    web
  1. client_id 应该是 Service id.对于apps,它应该是App bundle id.(即使您使用原生苹果对话框获取 code 并稍后将其传递给网络服务器,然后使用它来请求令牌 API.) JWT 调用中的 sub 应该与client_id.在苹果论坛查看答案
  2. 您的 JWT 库不支持 Apple 登录所需的加密.他们为此使用 JWT 标准,使用带有 P-256 曲线和 SHA256 哈希的椭圆曲线算法.换句话说,他们使用 ES256 JWT 算法.一些 JWT 库不支持椭圆曲线方法,因此在开始尝试之前确保您的库支持.ES256 和 invalid_client
  3. 令牌中的日期.尝试设置以下

<块引用>

 expires: DateTime.UtcNow.AddDays(2),//有效期最长为 6 个月发布时间:DateTime.UtcNow.AddDays(-1),notBefore: DateTime.UtcNow.AddDays(-1),

我的网络服务器上的 invalid_client 失败了,因为 Apple 认为它是未来的证书,当时我有:

 expires: DateTime.UtcNow.AddMinutes(5),//有效期最长为 6 个月发布时间:DateTime.UtcNow,notBefore: DateTime.UtcNow,

  1. 在调用令牌 API 时指定 User-Agent 标头也很重要.还值得一提的是,curl 可能会抛出此错误,而当您从 Web 服务器调用它时它会正常工作.
  2. 确保您设置了正确的 Content-Type: application/x-www-form-urlencoded 标头,而不是某些库的 Content-Type: application/json比如默认设置的axios.

I'm trying to implement Sign In with Apple with an iOS app and a backend. The goal is this:

  1. The User signs in on the iOS app
  2. After a positive response the app calls an endpoint on the backend and hands over the authorizationCode
  3. The backend now needs to verify the authorizationCode with another call to apple's server.

Here I'm confused. In order to make this call, the backend needs to provide a bunch of parameters:

URL

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

Query Parameters

client_id     = com.mycompany.appname
client_secret = ...
code          = ... // `authorizationCode` from the signin in the iOS app
grant_type    = authorization_code

I've generated a JWT for the client_secret:

JWT Properties

header:
    kid: <key id, created on Apple Dev Portal>
claims:
    iss: <team id>
    iat: <current timestamp>
    exp: <current timestamp + 180 days>
    aud: "https://appleid.apple.com"
    sub: "com.mycompany.appname"

Yesterday I've created two keys for two apps (A and B) on the Dev Portal, used it to generate secrets and today app A worked and I've got a positive response:

Positive response

{
    "access_token" : "a1e64327924yt49f5937d643e25a48b81.0.mxwz.GN9TjJIJ5_4dR6WjbZoVNw",
    "token_type" : "Bearer", 
    "expires_in" : 3600, 
    "refresh_token" : "rca76d9ebta644fde9edba269c61eeb41.0.mxwz.sMDUlXnnLLUOu2z0WlABoQ", 
    "id_token" : "eyJraWQiOiJBSURPUEsxIcccYWxnIjoiUlMyNTYifQ.eyJpc3MiOiJodHRwczovL2FwcGxlaWQuYXBwbGUuY29tIiwiYXVkIjoiZGUudHJ1ZmZscy5hcHBsZS1zaWduaW4tdGVzdCIsImV4cCI6MTU2NzcwMDI0MiwiaWF0IjoxNTY3Njk5NjQyLCJzdWaaaiIwMDA3NjkuYWY3NDdjMTlmZGRmNDJhNjhhYmFkZjhlNTQ1MmY3NjAuMjIwNSIsImF0X2hhc2giOiJrVThQTkZOUHYxS0RGUEtMT2hIY213IiwiYXV0aF90aW1lIjoxNTY3Njk5NjM5fQ.g3JD2MDGZ6wiVS9VMHpj24ER0XqJlunatmqpE7sRarMkhMHMTk7j8gty1lpqVBC6Z8L5CZuewdzLuJ5Odrd3_c1cX7gparTQE4jCyvyTACCPKHXReTC2hGRIEnAogcxv6HDWrtZgb3ENhoGhZW778d70DUdd-e4KKiAvzLOse-endHr51PaR1gv-cHPcwnm3NQZ144I-xhpU5TD9VQJ9IgLQvZGZ8fi8SOcu6rrk5ZOr0mpt0NbJNGYgH5-8iuSxo18QBWZDXoEGNsa4kS5GDkq5Cekxt7JsJFc_L1Np94giXhpbYHqhcO1pZSGFrJVaMvMMftZfuS_T3sh2yCqkcA"
}

B, however, still doesn't work. Today I revoked the key for A and created a new one and now it doesn't work anymore with the new one, but still with the old one, even though I deleted it on the Dev Portal. I'm so confused.

Response Error:

{
    "error": "invalid_client"
}

I wonder if Apple needs some time indexing or something like that. I just want to understand how this works.

解决方案

There are several reasons why it could happen:

  1. client_id for web should be Service id. For apps it should be App bundle id. (Even if you use native apple dialog get code and later pass it to a webserver and then use it to request token API.) sub in JWT call should be the same as client_id. See the answer there Apple forum
  2. Your JWT library does not support encryption required by Apple sign-in. They use the JWT standard for this, using an elliptic curve algorithm with a P-256 curve and SHA256 hash. In other words, they use the ES256 JWT algorithm. Some JWT libraries don’t support elliptic curve methods, so make sure yours does before you start trying this out. ES256 and invalid_client
  3. Dates in token. Try to set the following

 expires: DateTime.UtcNow.AddDays(2), // expiry can be a maximum of 6 months
 issuedAt: DateTime.UtcNow.AddDays(-1),
 notBefore: DateTime.UtcNow.AddDays(-1),

It failed with invalid_client on my webserver, since Apple considered it as a certificate from the future, when I had:

 expires: DateTime.UtcNow.AddMinutes(5), // expiry can be a maximum of 6 months
 issuedAt: DateTime.UtcNow,
 notBefore: DateTime.UtcNow,

  1. It's also important to specify the User-Agent header when you call the token API. It's also worth mentioning that curl can throw this error, while it will work fine when you call it from a web server.
  2. Make sure you are setting the correct Content-Type: application/x-www-form-urlencoded header instead of Content-Type: application/json that some libraries like axios set by default.

这篇关于使用 Apple 登录(iOS 应用 + 后端验证)API 返回错误“invalid_client";的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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