Я получаю сообщение об ошибке 400 : [{"error":"invalid_client"}]
при попытке обменять код авторизации на токен обновления. Я все перепробовал и перепроверил много раз. Я использую эту библиотеку для создания секрета клиента. Ниже я использовал образец ключа для демонстрации проблемы. Что могло быть не так?
Генератор секретов клиентов Apple
public class AppleClientSecretGenerator {
private String team_id;
private String sub;
private String key_id;
private long expiration_time;
private String secret_key;
private String aud;
public AppleClientSecretGenerator() {
super();
this.team_id = "***********";
this.sub = "com.example.app";
this.key_id = "**********";
this.expiration_time = 200000;
this.secret_key = "MIGTAFKMN23SFF2SFGSM49AgEGCCqGSM49AwEHBHdfDSFFDe09hGVEu5sesMNNF" +
"pet8GJDZIL0inL4oxgIJNF0i3Q8MYKOgsdCgYIKoZIzj0DAQehRANCAAQhAVyKVrFGWEw+" +
"gkWyeQNxopjG30iF56DXM0QfqwbffKmsdPkjfe3FKDDFyDYmk+XZM4qj6aIZKLy" +
"KLM4Nd23";
this.aud = "https://appleid.apple.com";
}
public String generate() {
String jws = "";
try {
byte[] keyBytes = Base64.getDecoder().decode(secret_key);
//byte[] keyBytes = Files.readAllBytes(Paths.get(filename));
KeyFactory keyFactory = KeyFactory.getInstance("EC");
PrivateKey key = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(keyBytes));
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.ES256;
long nowSeconds = System.currentTimeMillis();
Date now = new Date(nowSeconds);
long expMillis = nowSeconds + expiration_time;
Date exp = new Date(expMillis);
jws = Jwts.builder()
.setHeaderParam("kid", key_id)
.setIssuedAt(now)
.setSubject(sub)
.setIssuer(team_id)
.setAudience(aud)
.setExpiration(exp)
.signWith(key, signatureAlgorithm)
.compact();
} catch (JwtException e) {
//don't trust the JWT!
System.out.println("Error: " + e.getMessage());
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
System.out.println("Error: " + e.getMessage());
e.printStackTrace();
} catch (InvalidKeySpecException e) {
// TODO Auto-generated catch block
System.out.println("Error: " + e.getMessage());
e.printStackTrace();
}
System.out.println("Client Secret: " + jws);
return jws;
}
}
Запрос на авторизацию
public class AuthorizationRequest {
private String client_id;
private String client_secret;
private String code;
private String grant_type;
private String redirect_uri;
public AuthorizationRequest(String client_secret, String code) {
super();
this.client_id = "com.maxtrauboth.BopdropSwiftUI";
this.client_secret = client_secret;
this.code = code;
this.grant_type = "authorization_code";
this.redirect_uri = "http://mylocaladdr.test/";
}
// Getters and Setters here
Подтвердить пользователя
@PostMapping("verify")
public UserCredentials verify(@RequestBody UserCredentials credentials) {
Jwk jwk;
Algorithm algorithm;
// Validate identity token
DecodedJWT jwt = JWT.decode(credentials.getToken());
JwkProvider provider = new UrlJwkProvider("https://appleid.apple.com/auth/keys");
try {
jwk = provider.get(jwt.getKeyId());
algorithm = Algorithm.RSA256((RSAPublicKey) jwk.getPublicKey(), null);
algorithm.verify(jwt);
// Check expiration
if (jwt.getExpiresAt().before(Calendar.getInstance().getTime())) {
throw new RuntimeException("Expired token!");
}
// Create client_secret
AppleClientSecretGenerator generator = new AppleClientSecretGenerator();
String client_secret = generator.generate();
// Refreshing the token by sending the authorization code
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_FORM_URLENCODED));
headers.set("User-Agent", "Mozilla/5.0 Firefox/26.0");
System.out.println("Authorization Code: " + credentials.getAuthorization_code());
AuthorizationRequest request = new AuthorizationRequest(client_secret, credentials.getAuthorization_code());
HttpEntity<String> entity = new HttpEntity<String>(request.toString(), headers);
RestTemplate restTemplate = new RestTemplate();
// send POST request
TokenResponse response = restTemplate.postForObject("https://appleid.apple.com/auth/token", entity, TokenResponse.class);
// do some database work here
} catch (JwkException e) {
// error
} catch (IllegalArgumentException e) {
// error
}
// sending the token back to the user
return credentials;
}
Созданный секрет клиента
{
"kid": "*********",
"alg": "ES256"
}
{
"iss": "*********",
"iat": 1587930164,
"exp": 1587930364,
"aud": "https://appleid.apple.com",
"sub": "com.example.app"
}