新 Apple 登录不断抛出错误 HTTP 400 Invalid_grant

Jav*_*nes 8 java authentication spring ios

根据Apple doc验证针对Apple的身份验证代码,我们需要使用以下参数POST到http://appleid.apple.com/auth/token

#!java

token = generateJWT(keyId, teamId, clientId, certificatePath);

HttpResponse<String> response = Unirest.post(authUrl)
     .header("Content-Type", "application/x-www-form-urlencoded")
     .field("client_id", clientId)
     .field("client_secret", token)
     .field("grant_type", "authorization_code")
     .field("code", authorizationCode)
     .asString();

Run Code Online (Sandbox Code Playgroud)

在哪里:

  • authorization_code : 是应用客户端提供的授权码。

  • clientId:由 Apple 提供

  • 令牌:是客户端机密。使用以下代码生成 JWT:

#!java

private static String generateJWT(String keyId, String teamId, String clientId, String certificatePath) throws Exception {
        if (pKey == null) {
            pKey = getPrivateKey(certificatePath);
        }

        return Jwts.builder()
                .setHeaderParam(JwsHeader.KEY_ID, keyId)
                .setIssuer(teamId)
                .setAudience("https://appleid.apple.com")
                .setSubject(clientId)
                .setExpiration(new Date(System.currentTimeMillis() + (1000 * 60 * 5)))
                .setIssuedAt(new Date(System.currentTimeMillis()))
                .signWith(pKey, SignatureAlgorithm.ES256)
                .compact();
    }

private static PrivateKey getPrivateKey(String certificatePath) throws Exception {
        //read your key
        try (PEMParser pemParser = new PEMParser(new FileReader(certificatePath))) {
            final JcaPEMKeyConverter converter = new JcaPEMKeyConverter();
            final PrivateKeyInfo object = (PrivateKeyInfo) pemParser.readObject();
            final PrivateKey pKey = converter.getPrivateKey(object);
            return pKey;
        }
    }
Run Code Online (Sandbox Code Playgroud)

我们检查 JWT 是否包含苹果所需的所有字段:

#!json

{
  "alg": "ES256",
  "typ": "JWT",
  "kid": "6876D87D6"
}
{
  "iat": 1578654031,
  "exp": 1578740431,
  "aud": "https://appleid.apple.com",
  "iss": "57675576576",
  "sub": "com.blahblah.client"
}
Run Code Online (Sandbox Code Playgroud)

但这就是问题所在。它始终返回带有此正文的 400 HTTP 错误:

#!json

{"error":"invalid_grant"}
Run Code Online (Sandbox Code Playgroud)

从这里我们完全迷失了。我们不明白为什么代码不正确或者为什么它有一个 invalid_grant 错误。

小智 6

就我而言,前端identityToken错误发送,而不是authorizationCode. 那导致b'{"error":"invalid_grant"}'


Dev*_*B2F 3

我仅在向https://appleid.apple.com/auth/tokeninvalid_grant发送不正确的请求时才出现错误。确保您获取代码的方式与下面的 swift 代码示例中的方式相同。authorizationCode

我认为这个错误与client_secret. 当我将client_secret有效值更改为空字符串或某些不正确的值时,我只是收到错误invalid_client。当 theauthorizationCode和 the client_secret都错误时,我也会得到invalid_client错误。

这是请求所需要的:

  1. app_id 是应用程序的包标识符
  2. client_secret 是您使用问题中显示的信息创建的jwt令牌,并使用您从developer.apple.com下载的私钥进行签名也可以在此处查看我的答案

  3. grant_type 只是字符串“authorization_code”

  4. code 是您从应用程序内部获取的字符串格式的授权代码,而不是数据格式
data = {
    'client_id': app_id,
    'client_secret': client_secret,
    'grant_type': grant_type,
    'code': authorizationCode,
}

headers = {
    'Content-Type': 'application/x-www-form-urlencoded',
}

//python example request

response = requests.request(
    method='POST',
    url='https://appleid.apple.com/auth/token',
    data=data,
    headers=headers,
)

if response.status_code == 200:
    print("200")
else:
    print("error")
print(response.text)
Run Code Online (Sandbox Code Playgroud)

以下快速代码可用于获取正确格式的authorizationCode,identityToken和。userIdentifier

func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
    if let appleIDCredential = authorization.credential as? ASAuthorizationAppleIDCredential {

         let userIdentifier = appleIDCredential.user
         print("userIdentifier: \(userIdentifier)")

         let authorizationCode = String(data: appleIDCredential.authorizationCode!, encoding: .utf8)!
         print("authorizationCode: \(authorizationCode)")

         let identityToken = String(data: appleIDCredential.identityToken!, encoding: .utf8)!
         print("identityToken: \(identityToken)")

    }
}
Run Code Online (Sandbox Code Playgroud)