php - 如何将 Apple 授权码换成访问 token ?

标签 php oauth-2.0 jwt apple-sign-in

我很难弄清楚如何使用 Apple 登录。文档很糟糕,失败的回应让我们毫 headless 绪。 Aaron Parecki ( https://developer.okta.com/blog/2019/06/04/what-the-heck-is-sign-in-with-apple ) 的文章确实有点帮助,但我现在似乎陷入困境。

首先,我生成一个带有/auth/authorize 的登录 URL,如下所示:

$_SESSION['state'] = bin2hex(openssl_random_pseudo_bytes(16));

return 'https://appleid.apple.com/auth/authorize?' . http_build_query([
  'response_type' => 'code',
  'response_mode' => 'form_post',
  'client_id' => 'com.my.service.id',
  'redirect_uri' => 'https://my.app/redirect'),
  'state' => $_SESSION['state'],
  'scope' => 'name email',
]);

在努力完成域验证和返回 URL 之后,这将我带到 Apple 登录页面,并在成功登录后返回到我的 redirect_uri。然后,我需要授权我使用 Guzzle 执行的 token :

$response = (new Client)->request('POST', 'https://appleid.apple.com/auth/token', [
  RequestOptions::FORM_PARAMS => [
    'grant_type' => 'authorization_code',
    'code' => $_POST['code'],
    'redirect_uri' => 'https://my.app/redirect',
    'client_id' => 'com.my.service.id',
    'client_secret' => $this->getClientSecret(),
  ],
  RequestOptions::HEADERS => [
    'Accept' => 'application/json'
  ]
]);

return json_decode($response, true);

客户端密码是使用 Firebase php-jwt ( https://github.com/firebase/php-jwt ) 生成的,并通过 jwt.io 有效:

$key = openssl_pkey_get_private('file://certificate.p8');

return JWT::encode([
  'iss' => 'APPLETEAMID',
  'iat' => time(),
  'exp' => time() + 3600,
  'aud' => 'https://appleid.apple.com',
  'sub' => 'com.my.service.id',
], $key, 'ES256', 'certificate-id');

但是,向 Apple 执行 token 请求会返回 400 错误,并显示消息“invalid_client”。我无法确定我的客户端 ID/密码是否错误或重定向代码无效。有人可以指出我正确的方向吗?

编辑: 请注意,我覆盖了 JWT 类,允许使用 ES256。有关更多信息,请查看 this open pull request .

最佳答案

根据你说的,还有什么Apple在其文档中说,我认为您将 Apple 的 Identity token 误认为是 Client Secret

Apple 的 Identity Token 是一个 JWT token ,可唯一标识用户,是现有 OAuth 2.0 框架“之上”的安全层。

当您在授权服务器中注册/验证您的客户端时,基于 RFC 6749 - The OAuth 2.0 Authorization Framework ,您很可能从授权服务器收到一个 secret ,这是您客户端的 secret (即您服务器在 com.my.service.id 的密码),用于从获取 token 到使用身份检索资源。使用此 client_id/client_secret 对的建议方法是 HTTP 基本身份验证 方法,不鼓励使用 POST 参数。

The authorization server MUST support the HTTP Basic authentication scheme for authenticating clients that were issued a client password.

...

Including the client credentials in the request-body using the two parameters is NOT RECOMMENDED and SHOULD be limited to clients unable to directly utilize the HTTP Basic authentication scheme (or other password-based HTTP authentication schemes). The parameters can only be transmitted in the request-body and MUST NOT be included in the request URI.

您将以 JWT token 的形式收到用户的 Identity Token,您应该准确提供该 token 且不得篡改,因为此 token 是由 Apple 自己颁发的。但是,您可以检查负载(参见 JWT Introduction at jwt.io)以了解 Identity Token 的有效性 (iat + exp)。除非您正在为 Apple 的授权团队编写代码,否则不应生成 Identity Token

最后,我无法强调要彻底阅读 OAuth 规范并记住 Identity Token 是 Apple 向您发送用户 ID 的方式,但 client_id 和 client_secret 是 OAuth 规范中定义的内容。

关于php - 如何将 Apple 授权码换成访问 token ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57788966/

相关文章:

security - 使用 AspNetUserTokens 表在 ASP.NET Core Web Api 中存储刷新 token

php - 变量存在并且有一个值,并且仅返回一个 bool 值

java - 使用HttpClient进行登录认证

react-native - 无法从 Web View 中恢复控制以在 OAuth 流程中对 native 应用程序使用react

c# - 如何通过 Oauth2 身份验证使用 Google Contacts API

javascript - TypeError : jwt. 符号不是函数

PHP接口(interface)可选参数

Php变量不保存数据

Azure AD "Grant permission"按钮停止工作

go - 无法获取额外信息。来自 gin-jwt 中的登录响应