Sign in with Apple Java User Verification

前端 未结 2 2234
暖寄归人
暖寄归人 2020-12-09 19:11

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 j

2条回答
  •  一向
    一向 (楼主)
    2020-12-09 19:50

    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.Generate JWT from your key

    2.Send auth code with your token

    3.Decode response

    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 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();
    }
    
    
    }
    

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

     
        
            org.bouncycastle
            bcpkix-jdk15on
            1.63
        
    
    
        
            io.jsonwebtoken
            jjwt-api
            0.10.7
        
        
            io.jsonwebtoken
            jjwt-impl
            0.10.7
            runtime
        
        
            io.jsonwebtoken
            jjwt-jackson
            0.10.7
            runtime
        
    
    
        
            com.mashape.unirest
            unirest-java
            1.4.9
        
        
            org.apache.httpcomponents
            httpclient
            4.3.6
        
        
            org.apache.httpcomponents
            httpasyncclient
            4.0.2
        
        
            org.apache.httpcomponents
            httpmime
            4.3.6
        
        
            org.json
            json
            20140107
        
    

    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}
    

提交回复
热议问题