使用Apple登录(iOS应用+后端验证)API返回错误"invalid_client"; [英] Sign in with Apple (iOS App + Backend verification) API returns error "invalid_client"
问题描述
我正在尝试通过iOS应用和后端实施使用Apple登录.目标是这样:
I'm trying to implement Sign In with Apple with an iOS app and a backend. The goal is this:
- 用户在iOS应用上登录
- 得到肯定的响应后,应用程序将调用后端上的终结点并移交
authorizationCode
- 后端现在需要再次调用苹果服务器来验证
authorizationCode
.
- The User signs in on the iOS app
- After a positive response the app calls an endpoint on the backend and hands over the
authorizationCode
- 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
查询参数
client_id = com.mycompany.appname
client_secret = ...
code = ... // `authorizationCode` from the signin in the iOS app
grant_type = authorization_code
我为client_secret
生成了JWT
:
JWT属性
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"
昨天,我在开发门户网站上为两个应用程序(A和B)创建了两个密钥,并用它来生成秘密,而今天应用程序A起作用了,我得到了积极的回应:
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:
积极回应
{
"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仍然不起作用.今天,我撤消了A的密钥并创建了一个新密钥,现在即使在开发门户网站上将其删除,它也不再适用于新密钥,但仍然不能与旧密钥一起使用.我很困惑.
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.
响应错误:
{
"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:
-
网络的
-
client_id
应该是服务ID .对于应用,它应该是应用捆绑包ID . (即使您使用本机苹果对话框,也要获取code
并将其传递到Web服务器,然后使用它来请求令牌API.)JWT调用中的sub
应该与client_id
相同. 在苹果论坛上查看答案 - 您的JWT库不支持Apple登录所需的加密.他们为此使用了JWT标准,并使用了具有P-256曲线和SHA256哈希的椭圆曲线算法.换句话说,他们使用ES256 JWT算法.一些JWT库不支持椭圆曲线方法,因此在开始尝试之前,请确保您的椭圆曲线方法有效. ES256和invalid_client
- 日期标记.尝试设置以下内容
client_id
for web should be Service id. For apps it should be App bundle id. (Even if you use native apple dialog getcode
and later pass it to a webserver and then use it to request token API.)sub
in JWT call should be the same asclient_id
. See the answer there Apple forum- 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
- 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),
在我的Web服务器上,由于invalid_client失败,这是因为苹果将其视为将来的证书,
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,
- 在调用令牌API时指定 User-Agent 标头也很重要.还值得一提的是curl会引发此错误,而当您从Web服务器调用它时,它将正常工作.
- 请确保您设置的是正确的
Content-Type: application/x-www-form-urlencoded
标头,而不是Content-Type: application/json
,例如 axios a>默认设置.
- 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.
- Make sure you are setting the correct
Content-Type: application/x-www-form-urlencoded
header instead ofContent-Type: application/json
that some libraries like axios set by default.
这篇关于使用Apple登录(iOS应用+后端验证)API返回错误"invalid_client";的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!