Luk*_*ger 17 oauth ios jwt apple-id sign-in-with-apple
我正在尝试使用 iOS 应用程序和后端实现使用 Apple 登录。目标是这样的:
authorizationCodeauthorizationCode通过另一个对苹果服务器的调用来验证。在这里我很困惑。为了进行这个调用,后端需要提供一堆参数:
网址
https://appleid.apple.com/auth/token
Run Code Online (Sandbox Code Playgroud)
查询参数
client_id = com.mycompany.appname
client_secret = ...
code = ... // `authorizationCode` from the signin in the iOS app
grant_type = authorization_code
Run Code Online (Sandbox Code Playgroud)
我已经产生JWT了client_secret:
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"
Run Code Online (Sandbox Code Playgroud)
昨天我在 Dev Portal 上为两个应用程序(A 和 B)创建了两个密钥,用它来生成秘密,今天应用程序 A 工作,我得到了积极的回应:
正面回应
{
"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"
}
Run Code Online (Sandbox Code Playgroud)
但是,B 仍然不起作用。今天我撤销了 A 的密钥并创建了一个新的,现在它不再适用于新的,但仍然适用于旧的,即使我在 Dev Portal 上删除了它。我很困惑。
响应错误:
{
"error": "invalid_client"
}
Run Code Online (Sandbox Code Playgroud)
我想知道 Apple 是否需要一些时间索引或类似的东西。我只是想了解这是如何工作的。
可能发生的原因有多种:
client_id对于web应该是Service id。对于应用程序,它应该是App bundle id。(即使您使用本机 Apple dialog getcode然后将其传递给网络服务器,然后使用它来请求令牌 API。)sub在 JWT 调用中应该与client_id.
在苹果论坛上看到答案Run Code Online (Sandbox Code Playgroud)expires: DateTime.UtcNow.AddDays(2), // expiry can be a maximum of 6 months issuedAt: DateTime.UtcNow.AddDays(-1), notBefore: DateTime.UtcNow.AddDays(-1),
我的网络服务器上的 invalid_client 失败了,因为 Apple 认为它是未来的证书,当时我有:
expires: DateTime.UtcNow.AddMinutes(5), // expiry can be a maximum of 6 months
issuedAt: DateTime.UtcNow,
notBefore: DateTime.UtcNow,
Run Code Online (Sandbox Code Playgroud)
Content-Type: application/x-www-form-urlencoded标头,而不是Content-Type: application/json像axios这样默认设置的一些库。小智 8
关于如何从服务器端的 iOS 应用程序验证 Apple 登录,我一直在挠头,但找不到太多关于它的文档。
我将在 nodeJS 中实现我的实现,以防它对任何人有帮助;我实际上遵循了柯蒂斯赫伯特在这里概述的方法
{
"keys": [
{
"kty": "RSA",
"kid": "86D88Kf",
"use": "sig",
"alg": "RS256",
"n": "iGaLqP6y-SJCCBq5Hv6pGDbG_SQ11MNjH7rWHcCFYz4hGwHC4lcSurTlV8u3avoVNM8jXevG1Iu1SY11qInqUvjJur--hghr1b56OPJu6H1iKulSxGjEIyDP6c5BdE1uwprYyr4IO9th8fOwCPygjLFrh44XEGbDIFeImwvBAGOhmMB2AD1n1KviyNsH0bEB7phQtiLk-ILjv1bORSRl8AK677-1T8isGfHKXGZ_ZGtStDe7Lu0Ihp8zoUt59kx2o9uWpROkzF56ypresiIl4WprClRCjz8x6cPZXU2qNWhu71TQvUFwvIvbkE1oYaJMb0jcOTmBRZA2QuYw-zHLwQ",
"e": "AQAB"
},
{
"kty": "RSA",
"kid": "eXaunmL",
"use": "sig",
"alg": "RS256",
"n": "4dGQ7bQK8LgILOdLsYzfZjkEAoQeVC_aqyc8GC6RX7dq_KvRAQAWPvkam8VQv4GK5T4ogklEKEvj5ISBamdDNq1n52TpxQwI2EqxSk7I9fKPKhRt4F8-2yETlYvye-2s6NeWJim0KBtOVrk0gWvEDgd6WOqJl_yt5WBISvILNyVg1qAAM8JeX6dRPosahRVDjA52G2X-Tip84wqwyRpUlq2ybzcLh3zyhCitBOebiRWDQfG26EH9lTlJhll-p_Dg8vAXxJLIJ4SNLcqgFeZe4OfHLgdzMvxXZJnPp_VgmkcpUdRotazKZumj6dBPcXI_XID4Z4Z3OM1KrZPJNdUhxw",
"e": "AQAB"
}
]
}
Run Code Online (Sandbox Code Playgroud)
const axios = require('axios').default;
const jose = require('jose')
const {
JWKS, // JSON Web Key Set (JWKS)
JWT, // JSON Web Token (JWT)
errors // errors utilized by jose
} = jose
axios.get('https://appleid.apple.com/auth/keys')
.then(function (response) {
// handle success
const key = jose.JWKS.asKeyStore(response.data);
const verified = jose.JWT.verify(identityToken, key);
})
.catch(function (error) {
// handle error
console.log(error);
})
.then(function () {
// always executed
});
Run Code Online (Sandbox Code Playgroud)
最后,您会得到一个结构与解码 JWT (identityToken) 相同的对象,您可以在其中验证它;
{
"iss": "https://appleid.apple.com",
"aud": "BundleID",
"sub": "credential.user",
"email": "credential.email",
}
Run Code Online (Sandbox Code Playgroud)
您的本机 APP ID 是您的捆绑包 ID,以您的团队 ID 为前缀,并用点分隔。
“Apple 应用程序 ID 是一个由两部分组成的字符串,用于标识一个或多个应用程序。具体来说,Apple 应用程序 ID 是您的团队 ID 和捆绑包 ID,并用句点连接,例如:1A234H7ABC.com.yourdomain.YourApp。”
然而,我在让它发挥作用时遇到了同样的问题。