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エラーがある理由はわかりません。
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'
私の場合、フロントエンドがidentityToken
ではなく誤ってauthorizationCode
を送信しました。 b'{"error":"invalid_grant"}'