Войти с помощью Apple Java User Verification - PullRequest
3 голосов
/ 05 октября 2019

Я реализовал в приложении новую функцию Apple «Войти через Apple», но я не могу проверить код авторизации в моем бэкэнде. Мой бэкэнд написан на Java, и я не могу сгенерировать JWT и связаться с серверами Apple.

1 Ответ

1 голос
/ 05 октября 2019

Сначала зайдите на developer.apple.com -> Сертификаты, идентификаторы и профили -> Ключи. Создать ключ для Apple Войдите в систему и загрузите этот ключ. Вы не можете скачать этот ключ снова, поэтому храните его в безопасном месте и не делитесь с другими. Кроме того, ваш идентификатор ключа, показанный здесь, обратите внимание на это, оно понадобится вам позже. Вам также понадобится идентификатор команды. Если вы этого не знаете, в правом верхнем углу страницы написано, как ВАШЕ ИМЯ - XX0XX00XXX.

В основном вы выполните следующие действия.

1.Создайте JWT из своего ключа

2.Отправьте код авторизации с вашим токеном

3. Ответ кодирования

public class AppleLoginUtil {
private static String APPLE_AUTH_URL = "https://appleid.apple.com/auth/token";

private static String KEY_ID = "**********";
private static String TEAM_ID = "**********";
private static String CLIENT_ID = "com.your.bundle.id";

private static PrivateKey pKey;

private static PrivateKey getPrivateKey() throws Exception {
//read your key
    String path = new ClassPathResource("apple/AuthKey.p8").getFile().getAbsolutePath();

    final PEMParser pemParser = new PEMParser(new FileReader(path));
    final JcaPEMKeyConverter converter = new JcaPEMKeyConverter();
    final PrivateKeyInfo object = (PrivateKeyInfo) pemParser.readObject();
    final PrivateKey pKey = converter.getPrivateKey(object);

    return pKey;
}

private static String generateJWT() throws Exception {
    if (pKey == null) {
        pKey = getPrivateKey();
    }

    String token = Jwts.builder()
            .setHeaderParam(JwsHeader.KEY_ID, KEY_ID)
            .setIssuer(TEAM_ID)
            .setAudience("https://appleid.apple.com")
            .setSubject(CLIENT_ID)
            .setExpiration(new Date(System.currentTimeMillis() + (1000 * 60 * 5)))
            .setIssuedAt(new Date(System.currentTimeMillis()))
            .signWith(pKey, SignatureAlgorithm.ES256)
            .compact();

    return token;
}

/*
* Returns unique user id from apple
* */
public static String appleAuth(String authorizationCode) throws Exception {

    String token = generateJWT();

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

    TokenResponse tokenResponse=new Gson().fromJson(response.getBody(),TokenResponse.class);
    String idToken = tokenResponse.getId_token();
    String payload = idToken.split("\\.")[1];//0 is header we ignore it for now
    String decoded = new String(Decoders.BASE64.decode(payload));

    IdTokenPayload idTokenPayload = new Gson().fromJson(decoded,IdTokenPayload.class);

   return idTokenPayload.getSub();
}


}

Я использовал BouncyCastle jjwt для генерации токена. А также unirest и gson для остальных вызовов.

 <!-- https://mvnrepository.com/artifact/org.bouncycastle/bcpkix-jdk15on -->
    <dependency>
        <groupId>org.bouncycastle</groupId>
        <artifactId>bcpkix-jdk15on</artifactId>
        <version>1.63</version>
    </dependency>

<!--JJWT-->
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt-api</artifactId>
        <version>0.10.7</version>
    </dependency>
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt-impl</artifactId>
        <version>0.10.7</version>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt-jackson</artifactId>
        <version>0.10.7</version>
        <scope>runtime</scope>
    </dependency>

<!--UNIREST-->
    <dependency>
        <groupId>com.mashape.unirest</groupId>
        <artifactId>unirest-java</artifactId>
        <version>1.4.9</version>
    </dependency>
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.3.6</version>
    </dependency>
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpasyncclient</artifactId>
        <version>4.0.2</version>
    </dependency>
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpmime</artifactId>
        <version>4.3.6</version>
    </dependency>
    <dependency>
        <groupId>org.json</groupId>
        <artifactId>json</artifactId>
        <version>20140107</version>
    </dependency>

Я также проанализировал ответы на эти классы, если вы хотите знать.

public class TokenResponse {

private String access_token;
private String token_type;
private Long expires_in;
private String refresh_token;
private String id_token;

..getters and setters}

public class IdTokenPayload {

private String iss;
private String aud;
private Long exp;
private Long iat;
private String sub;//users unique id
private String at_hash;
private Long auth_time;

..getters and setters}
...