How to verify identityToken from "Sign In with Apple"?

Viewed 4554

I'm trying to verify the identity token I got from the "Sign In with Apple" service.

The document says the identity token is a JSON Web Token(JWT), but I got the identity token as following format:

identityToken = ZXlKcmFXUWlPaUpCU1VSUFVFc3hJaXdpWVd4bklqb2lVbE15TlRZaWZRLmV5SnBjM01pT2lKb2RIUndjem92TDJGd2NHeGxhV1F1WVhCd2JHVXVZMjl0SWl3aVlYVmtJam9pWTI5dExteHZiMjVuTG5Oa2F5NTBaWE4wTG05MlpYSnpaV0VpTENKbGVIQWlPakUxTnpBNE5qSTJPVElzSW1saGRDSTZNVFUzTURnMk1qQTVNaXdpYzNWaUlqb2lNREF4TURNNUxqSXpNemxrWXpReU9XWXhPVFExWW1NNVpqQXpZekU1T1RVeU1HUXlZMlUwTGpBek1EWWlMQ0pqWDJoaGMyZ2lPaUpoWkhZMFEyVnZSMjF5VDNWbVZrbG9SRzl4TFhobklpd2lZWFYwYUY5MGFXMWxJam94TlRjd09EWXlNRGt5ZlEuT19nTm1hTDdtd1hXcUpKX1ZIaElzT25IYWF4cnM0a1VWMVJzWjZwWEdHT1JFcnAxeXU0TzRzcWwtbnJrRl9xR2pRN2syLWxoQ25BWnRYOC13ektRNUM3M0NZZTFJRW1VTUFSS2ItYk1fdGx2YlVscmhXRGhkSjZSWVdpaTEwVklyN0oway1pZlEyb3lXUmRUTnNDTmpBaHM4SVMzYWxfQ0RqajhyY2hQa1djRHBKMGdqSm9Bamhua2hFRlllVWMxMWxaazFHVmRITXVoN3hqNUotVW1HNFNlczJ0OXBvcjZaTjZhc0lucENnM3lKaU5YREtMRDg2enRtc1NEem1rTGhFX2JLLWhaZlRRakNTSWx4TDJobm82NlVPbVJfMTNibDdsRmo0cTF3RVVQeFRCMDZGcTBBNkRXQ1lVa1ZaN0dScVhCWURDNUNqX2hhd2ZHUTIwandR

This token is not a JWT format. How should I handle with the identity token to get the JWT format?

4 Answers

I am pretty sure you are base64 encoding the string again. Just make a string of it and you are fine

String(data: appleIdCredential.identityToken!, encoding: .utf8)

There is probably something wrong with your "Sign In with Apple". That should return a response like :

{
  "authorizationCode": ...,
  "identityToken": ...,
  "realUserStatus": ...,
  "user": ...
}

Where "identityToken" is what you're looking for, a JWT token with the following informations :

{
  "iss": "https://appleid.apple.com",
  "aud": ...,
  "exp": 1575106544,
  "iat": 1575105944,
  "sub": ...,
  "c_hash": ...,
  "email": ...,
  "email_verified": "true",
  "is_private_email": "true",
  "auth_time": 1575105944
}

Here is the doc : https://developer.apple.com/documentation/signinwithapplerestapi/authenticating_users_with_sign_in_with_apple

The identity token will be in base64 encoding. You can print it out in the debugger like

po String(data: appleIdCredential.identityToken!, encoding: .utf8)!

And then you can copy the output of that to jwt.io to inspect the contents of it.

(Your example value is not a valid jwt value, so I'm not sure where you are getting it from.)

just pass id token to decode function

func decode(jwtToken jwt: String) -> [String: Any] {
  let segments = jwt.components(separatedBy: ".")
  return decodeJWTPart(segments[1]) ?? [:]
}

func base64UrlDecode(_ value: String) -> Data? {
  var base64 = value
    .replacingOccurrences(of: "-", with: "+")
    .replacingOccurrences(of: "_", with: "/")

  let length = Double(base64.lengthOfBytes(using: String.Encoding.utf8))
  let requiredLength = 4 * ceil(length / 4.0)
  let paddingLength = requiredLength - length
  if paddingLength > 0 {
    let padding = "".padding(toLength: Int(paddingLength), withPad: "=", startingAt: 0)
    base64 = base64 + padding
  }
  return Data(base64Encoded: base64, options: .ignoreUnknownCharacters)
}

func decodeJWTPart(_ value: String) -> [String: Any]? {
  guard let bodyData = base64UrlDecode(value),
    let json = try? JSONSerialization.jsonObject(with: bodyData, options: []), let payload = json as? [String: Any] else {
      return nil
  }

  return payload
}

like:

let jwt = try decode(jwtToken: stringToken)

and then you can get your required data like:

let _ = jwt[""] as? String

Related