Hello,
I have implemented Sign in with Apple in my iOS app and am currently trying to implement the revocation feature. However, I keep encountering an invalid_client error when calling the Apple authentication/revocation API.
Here are the details of my configuration:
Team ID: HUGD2H952H
Client ID: com.puppylink.puppylinkapp
Key ID: KXSYK98424
I am using these details to generate a client secret with the JWT ES256 algorithm. Below is the code I am using on the backend server to generate the client secret:
private fun makeClientSecret(): String {
val now: ZonedDateTime = ZonedDateTime.now(ZoneOffset.UTC)
val expirationTime: ZonedDateTime = now.plusMinutes(5) // Setting expiration time to 5 minutes
return Jwts.builder()
.setHeaderParam(JwsHeader.KEY_ID, appleProperties.keyId)
.setHeaderParam("alg", "ES256")
.setIssuer(appleProperties.teamId)
.setIssuedAt(Date.from(now.toInstant()))
.setExpiration(Date.from(expirationTime.toInstant()))
.setAudience("https://appleid.apple.com")
.setSubject(appleProperties.clientId)
.signWith(getPrivateKey(), SignatureAlgorithm.ES256)
.compact()
}
private fun getPrivateKey(): PrivateKey {
val resource = ClassPathResource(appleProperties.privateKeyFile)
val privateKey = String(Files.readAllBytes(Paths.get(resource.uri)))
val pemReader: Reader = StringReader(privateKey)
val pemParser = PEMParser(pemReader)
val converter = JcaPEMKeyConverter()
val keyInfo = pemParser.readObject() as PrivateKeyInfo
return converter.getPrivateKey(keyInfo)
}
}
Additionally, here is the code used to call the Apple authentication API from the backend server:
@Service
class AppleAuthService(
private val appleProperties: AppleProperties,
) {
private val logger = LoggerFactory.getLogger(javaClass)
private val restTemplate = RestTemplate()
fun getTokens(authorizationCode: String): TokenResponse {
try {
val clientSecret = makeClientSecret()
val formData: MultiValueMap<String, String> = LinkedMultiValueMap()
formData.add("client_id", appleProperties.clientId)
formData.add("client_secret", clientSecret)
formData.add("code", authorizationCode)
formData.add("grant_type", "authorization_code")
val headers = HttpHeaders()
headers.contentType = MediaType.APPLICATION_FORM_URLENCODED
val requestEntity = HttpEntity(formData, headers)
val response =
restTemplate.postForObject(
"https://appleid.apple.com/auth/token",
requestEntity,
TokenResponse::class.java,
)
return response ?: throw RuntimeException("Failed to retrieve tokens from Apple")
} catch (ex: Exception) {
logger.error("Error retrieving tokens: ", ex)
throw ex
}
}
data class TokenResponse(
val access_token: String,
val expires_in: Long,
val id_token: String,
val refresh_token: String,
val token_type: String,
)
Despite generating the client secret correctly, I am still receiving the invalid_client error when calling the API. Could you please help me identify the cause of this error and provide guidance on how to resolve it?
Thank you.
Selecting any option will automatically load the page