web-dev-qa-db-ja.com

新規AppleサインインがエラーHTTP 400 Invalid_grantをスローし続ける

Apple doc によると、認証コードをAppleに対して検証するには、POST to 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();

どこ:

  • authorization_code:アプリクライアントによって提供される認証コードです。

  • clientId:Appleによって提供されます

  • token:クライアントシークレットです。 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;
        }
    }

JWTにAppleが必要とするすべてのフィールドが含まれていることを確認します。

#!json

{
  "alg": "ES256",
  "typ": "JWT",
  "kid": "6876D87D6"
}
{
  "iat": 1578654031,
  "exp": 1578740431,
  "aud": "https://appleid.Apple.com",
  "iss": "57675576576",
  "sub": "com.blahblah.client"
}

しかし、これが問題です。それは常にこのボディで400 HTTPエラーを返します:

#!json

{"error":"invalid_grant"}

ここから私たちは完全に失われました。コードが正しくない理由や、コードにinvalid_grantエラーがある理由はわかりません。

4
Javier Sivianes

Appleバックエンドを使用してiOSアプリにサインインするときにDjangoバックエンドを使用しました。以下のエラーが発生しました:

<Response [400]> {'error': 'invalid_grant'}

私たちの問題は、バックエンドに送信する前に、authcodeをアプリから.utf8としてデコードしていたことです。 .utf8からUnicode.ASCIIに変更して問題を解決しました。

func authorizationController(controller: ASAuthorizationController,
                             didCompleteWithAuthorization authorization: ASAuthorization) {
    let credential = authorization.credential as? ASAuthorizationAppleIDCredential
    guard let authorizationCode = credential?.authorizationCode else {
        return
    }
    let authCode = String(decoding: authorizationCode, as: Unicode.ASCII.self)
    print(authCode)
}

この変更後、Appleから適切な応答を得ました。

<Response [200]> {'access_token': 'a80578f5ad9xxx.x.xxx.xxxx'
0
christijk

私の場合、フロントエンドがidentityTokenではなく誤ってauthorizationCodeを送信しました。 b'{"error":"invalid_grant"}'

0
phuongtm