Sign in with Apple verification Java invalid_client

What I try to achieve:



iOS client sends a JWT token to the backend.

Backend (Java) calls https://appleid.apple.com/auth/token to verify the token.

what I have so far:



to make Apple verification call:


        restTemplate = new RestTemplate();


        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
        map.add("client_id", clientId); // app_id like com.app.id
        String token = generateJWT();   // generated jwt
        map.add("client_secret", token);
        map.add("grant_type", "authorization_code");
        map.add("code", authorizationCode);  // JWT code we got from iOS
        HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);


        final String appleAuthURL = "https://appleid.apple.com/auth/token";
        String response = restTemplate.postForObject(appleAuthURL, request, String.class);

token generation:

        final PrivateKey privateKey = getPrivateKey();
        final int expiration = 1000 * 60 * 5;


        String token = Jwts.builder()
                .setHeaderParam(JwsHeader.KEY_ID, keyId) // key id I got from Apple
                .setIssuer(teamId)
                .setAudience("https://appleid.apple.com")
                .setSubject(clientId) // app id com.app.id
                .setExpiration(new Date(System.currentTimeMillis() + expiration))
                .setIssuedAt(new Date(System.currentTimeMillis()))
                .signWith(SignatureAlgorithm.ES256, privateKey) // ECDSA using P-256 and SHA-256
                .compact();


        return token;

to get my private key from the file:

        final Reader pemReader = new StringReader(getKeyData());
        final PEMParser pemParser = new PEMParser(pemReader);
        final JcaPEMKeyConverter converter = new JcaPEMKeyConverter();
        final PrivateKeyInfo object = (PrivateKeyInfo) pemParser.readObject();
        final PrivateKey pKey = converter.getPrivateKey(object);



I confirmed my JWT has all required fields:

{
  "kid": "SAME KEY AS MY KEY ID",
  "alg": "ES256"
}


{
  "iss": "Blahblah",
  "aud": "https://appleid.apple.com",
  "sub": "com.app.id",
  "exp": 1578513833,
  "iat": 1578513533
}

Replies

Hi Irina, where is your User-Agent header, which should be on line 6 of the first code snippet which is mandatory when you call apple token api?

There is a chance you have the same problem as I had:

https://forums.developer.apple.com/thread/128041

Irisha, sure you already solved it, but I hope this helps others.


Your code is fine, but you need to add the algorithm header:

.setHeaderParam(JwsHeader.ALGORITHM,"ES256")

in order to get it working


regards