I am trying to implement Sign in with Apple in my iOS app and Django Rest Framework (DRF) application. I want to know if I understand the workflow correctly.
Currently, I am using the libraries python-social-auth and rest_social_auth, and rest_framework_simplejwt.authentication.JWTAuthentication for authentication. The problem is that I set the refresh tokens to expire in one week (this should really be one day). At that point, I need to use the refresh token that Apple originally returned in their first authentication request, but python-social-auth does not persist those.
Specifically, I am wondering how I can get access to those original refresh tokens. More generally, I am wondering if this functionally has already been written in python-social-auth.
After a year and a half, "I" finally figured this out.
I was conflating the device Sign in with Apple with the Sign in with Apple Rest API. If you are developing in iOS/React Native, you do not need to make any calls to the Sign in with Apple Rest API.
You do need to make a call to an Apple auth server, but not a Sign in with Apple Rest API server. The Apple auth server will return a public key that you use to then confirm the authenticity of the identity token that Apple send to you on the device.
I borrowed heavily from this Gist, but I believe it is outdated because Apple is now cycling through (at least at the time of this post) 3 different keys. I also used Chris Herbert's post as a resource.
def _fetch_apple_public_key(kid):
global APPLE_LAST_KEY_FETCH
global APPLE_PUBLIC_KEYS
apple_public_key = APPLE_PUBLIC_KEYS.get(kid)
if (APPLE_LAST_KEY_FETCH + APPLE_KEY_CACHE_EXP) < int(time()) or apple_public_key is None:
keys_payload = requests.get(APPLE_PUBLIC_KEY_URL).json()
for key_payload in keys_payload["keys"]:
if key_payload.get('kid') == kid:
APPLE_PUBLIC_KEYS[kid] = RSAAlgorithm.from_jwk(json.dumps(key_payload))
APPLE_LAST_KEY_FETCH = int(time())
return APPLE_PUBLIC_KEYS[kid]
You can get the kid from the header of the identity token:
headers = jwt.get_unverified_header(user_token)
kid = headers.get('kid')