Apple Sign-in: Invalid_grant

After successfully logging in using apple sign-in. I get back the default response: the authorization code.
I send the entire payload to my backend to which I then, use the docs to verify the auth_code. I get back this response.
Code Block
{
"error": "invalid_grant",
"error_description": "client_id mismatch. The code was not issued to com.example.bundle."
}

I've checked the bundleId several times. I've created new Identifiers and keys, used those new values instead and I get the same issue. According to the errorResponse documentation:

invalid_grant
The authorization grant or refresh token is invalid, typically due to a mismatched or invalid client identifier, invalid code (expired or previously used authorization code), or invalid refresh token.

Any recommended test solutions to diagnose this issue?

Accepted Reply

So the issue is the apple sign-in doesn't give back a valid response i.e id_token, authorization_code when using an emulator. Bundling the app on TestFlight then, signing in on an actual device returned the correct response.
NOTE: I'm using Expo/React Native.

Replies

Hi tony308,

I've checked the bundleId several times. I've created new Identifiers and keys, used those new values instead and I get the same issue. [...]

The client_id must be identical to the client_id used to receive the initial authorization response. If you are authorizing on iOS, the authorization grant code validation must use the iOS bundle ID as well; otherwise, if you received the grant code via your client_id should be your Services ID created for the web application. Whenever these client_id values mismatch, the grant code validation will fail as the code was issued for another client.

If this is not the case, please submit a Technical Support Incident and I can take a deeper look into your scenario.
So the issue is the apple sign-in doesn't give back a valid response i.e id_token, authorization_code when using an emulator. Bundling the app on TestFlight then, signing in on an actual device returned the correct response.
NOTE: I'm using Expo/React Native.

I encounter the same issue even when testing with TestFlight. my verification code in java:




 logger.info("Apple authorization validation");
        // get the subject received from the client
        String clientSubject = getSubject(identityToken);

        // verifying the code by the apple server
        String token = getToken();
        logger.debug("Authorize with token:" + token);

        Map<String, String> params = new HashMap<>();
        params.put("client_id", CdConfig.APPLE_CLIENT_ID);
        params.put("client_secret", token);
        params.put("code", authorisationCode);
        params.put("grant_type", "authorization_code");
        params.put("redirect_uri", "");
        if (redirectURI != null) {

        }
        String response = post(CdConfig.APPLE_AUTH_URL, params);
        logger.info("Apple authorization response:" + response);

        AppleTokenResponse tokenResponse = objectMapper.readValue(response, AppleTokenResponse.class);
        if (tokenResponse.getError() != null && tokenResponse.getError().length() > 0) {
            logger.warn("Error during verification of the code. Reason:" + tokenResponse.getError());
            return null;
        }

        String serverSubject = getSubject(tokenResponse.getId_token());
        if (!serverSubject.equals(clientSubject)) {
            logger.warn("Validation failed, subject does not match!");
            return null;
        }

        return getClaims(tokenResponse.getId_token());

myJwt Token :

return Jwts.builder()
                .setHeaderParam(JwsHeader.KEY_ID, CdConfig.APPLE_KEY_ID)
                .setHeaderParam(JwsHeader.ALGORITHM,"ES256")
                .setIssuer(CdConfig.APPLE_TEAM_ID)
                .setAudience(CdConfig.APPLE_APPLE_ID_URL)
                .setSubject(CdConfig.APPLE_CLIENT_ID)
                .setExpiration(new Date(System.currentTimeMillis() + (1000 * 60 * 5)))
                .setIssuedAt(new Date(System.currentTimeMillis()))
                .signWith(SignatureAlgorithm.ES256, pKey)
                .compact();