I configured the login URL as follows:
https://appleid.apple.com/auth/authorize?
client_id={client_id}
&redirect_uri={redirect_uri}
&response_type=code%20id_token
&state=state
&scope=name%20email
&response_mode=form_post
According to the Apple documentation, the response to these requests should include the state, code, id_token, and user fields.
However, in my case, the user field is not returned and the id_token does not include user information.
Here is my code:
@RestController
public class CallBackController {
private final CreateSecret secret;
public CallBackController(CreateSecret secret) {
this.secret = secret;
}
@PostMapping(value = "/callback")
public ResponseEntity<Info> test(@RequestParam Map<String, String> params) throws Exception {
var res = secret.login(params.get("code"));
return new ResponseEntity<>(res, HttpStatus.OK);
}
}
@Service
public class CreateSecret {
@Value("${apple.team-id}")
private String APPLE_TEAM_ID;
@Value("${apple.login-key}")
private String APPLE_LOGIN_KEY;
@Getter
@Value("${apple.client-id}")
private String APPLE_CLIENT_ID;
@Value("${apple.redirect-url}")
private String APPLE_REDIRECT_URL;
@Value("${apple.key-path}")
private String APPLE_KEY_PATH;
private final static String APPLE_AUTH_URL = "https://appleid.apple.com";
public Info login(String code) throws Exception {
String userId;
String email;
String accessToken;
JSONParser jsonParser = new JSONParser();
JSONObject jsonObj = (JSONObject) jsonParser.parse(generateAuthToken(code));
System.out.println(jsonObj.toJSONString());
SignedJWT signedJWT = SignedJWT.parse((String) jsonObj.get("id_token"));
JWTClaimsSet getPayload = signedJWT.getJWTClaimsSet();
JSONObject payload = (JSONObject) jsonParser.parse(JSONValue.toJSONString(getPayload.toJSONObject()));
System.out.println(payload.toJSONString()); // Result that printed not include info
return Info.of("userId", "email"); // Temporary
}
public String generateAuthToken(String code) throws IOException {
if (code == null) throw new IllegalArgumentException("Failed get authorization code");
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
params.add("grant_type", "authorization_code");
params.add("client_id", APPLE_CLIENT_ID);
params.add("client_secret", createClientSecretKey());
params.add("code", code);
params.add("redirect_uri", APPLE_REDIRECT_URL);
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
HttpEntity<MultiValueMap<String, String>> httpEntity = new HttpEntity<>(params, headers);
try {
ResponseEntity<String> response = restTemplate.exchange(
APPLE_AUTH_URL + "/auth/token",
HttpMethod.POST,
httpEntity,
String.class
);
return response.getBody();
} catch (HttpClientErrorException e) {
throw new IllegalArgumentException("Apple Auth Token Error");
}
}
public String createClientSecretKey() throws IOException {
Map<String, Object> headerParamsMap = new HashMap<>();
headerParamsMap.put("kid", APPLE_LOGIN_KEY);
headerParamsMap.put("alg", "ES256");
return Jwts
.builder()
.setHeaderParams(headerParamsMap)
.setIssuer(APPLE_TEAM_ID)
.setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + 1000 * 30))
.setAudience(APPLE_AUTH_URL)
.setSubject(APPLE_CLIENT_ID)
.signWith(SignatureAlgorithm.ES256, getPrivateKey())
.compact();
}
private PrivateKey getPrivateKey() throws IOException {
ClassPathResource resource = new ClassPathResource(APPLE_KEY_PATH);
String privateKey = new String(resource.getInputStream().readAllBytes());
Reader pemReader = new StringReader(privateKey);
PEMParser pemParser = new PEMParser(pemReader);
JcaPEMKeyConverter converter = new JcaPEMKeyConverter();
PrivateKeyInfo object = (PrivateKeyInfo) pemParser.readObject();
return converter.getPrivateKey(object);
}
}
I tried changing the login URL and editing my application code, but the id_token still does not include user information and the JSON response does not include the user field.
Any help would be appreciated.