如何用Apple授权码交换访问令牌?

时间:2019-09-04 12:59:34

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

我很难弄清楚如何在Apple中使用该登录。文档非常糟糕,失败的响应使我们毫无头绪。 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执行的令牌:

$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发出的令牌请求会返回400错误,并显示消息“ invalid_client”。我无法弄清楚我的client-id / secret是否错误或重定向中的代码无效。有人可以指出我正确的方向吗?

编辑: 请注意,我重写了JWT类,从而允许使用ES256。有关更多信息,请检查this open pull request

1 个答案:

答案 0 :(得分:-2)

根据您所说的内容以及Apple在其文档中所说的内容,我认为您将Identity token与Apple的Client Secret相混淆。

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

当您基于RFC 6749 - The OAuth 2.0 Authorization Framework在授权服务器中注册/验证客户端时,您很可能会收到来自授权服务器的秘密,这是客户端的秘密(即,{{ 1}})用于从获取令牌到使用身份检索资源的每个请求。建议使用此com.my.service.id对的方法是client_id/client_secret方法,不建议使用POST参数。

  

授权服务器必须支持HTTP Basic      验证方案,用于验证已发出的客户端      客户密码。

     

...

     

使用两者在请求正文中包含客户端凭据      不推荐使用参数,并且应仅限于无法访问的客户端      直接利用HTTP基本身份验证方案(或其他      基于密码的HTTP身份验证方案)。该参数只能      在请求正文中传输,且不得包含在      请求URI。

您将以JWT令牌的形式收到用户的HTTP Basic Authentication,并且您应该准确地提供该令牌,并且不得对其进行篡改,因为该令牌是Apple本身发行的。但是,您可以检查有效载荷(请参阅JWT Introduction at jwt.io)以了解Identity Token的有效性(iat + exp)。除非您要为Apple的授权团队进行编码,否则不应该生成Identity Token

最后,我没有足够的压力来彻底阅读OAuth规范,并记住Identity Token是Apple向您发送用户ID的方式,但是client_id和client_secret是OAuth规范中定义的。

相关问题