本文介绍了使用Apple Java用户验证登录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经实现了新的Apple功能使用Apple登录"的应用程序端,但是我无法在后端使用AuthorizationCode进行验证.我的后端是用Java编写的,无法生成JWT并无法与Apple服务器通信.

I've implemented the app side of the new apple feature "Sign in with Apple" but i'm unable to verificate with authorizationCode in my backend. My backend is written in java and i'm unable to generate JWT and communicate with Apple servers.

推荐答案

首先访问developer.apple.com->证书,标识符和证书;个人资料->键.为Apple登录生成密钥并下载该密钥.您无法再次下载此密钥,因此请将其保存在安全的地方,不要与他人共享.另外,此处显示的密钥ID"也要注意这一点,以后将需要它.您还需要团队ID.如果您不知道,它会写在页面的右上角,例如YOURNAME-XX0XX00XXX.

First go developer.apple.com -> Certificates, Identifiers & Profiles -> Keys. Generate a key for Apple Sign in and download this key. You can not download this key again so keep it in a safe place and don't share with others. Also your Key ID shown here note this, you'll need this later. You'll also need team id. If you don't know it, it's written top right of the page like YOURNAME - XX0XX00XXX.

您将基本上遵循以下步骤.

You will basicly follow these steps.

1.通过密钥生成JWT

1.Generate JWT from your key

2.使用令牌发送身份验证代码

2.Send auth code with your token

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进行休息电话.

I've used BouncyCastle jjwt for generating token. And also unirest and gson for rest calls.

 <!-- 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>

如果您想知道的话,我也解析了对这些类的响应.

I've also parsed the responses to these classes if you wanted to know.

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}

这篇关于使用Apple Java用户验证登录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

05-16 08:24