Background
The integration of Sign In with Apple into applications has become increasingly popular due to its convenience and privacy-focused approach. However, navigating the token validation process and retrieving user information can be a complex task for developers. This article aims to demystify this process specifically for Python developers, offering a step-by-step guide on how to validate tokens obtained through Sign In with Apple and efficiently access user data within your application. By delving into the intricacies of token validation and user information retrieval, this comprehensive guide aims to equip developers with the knowledge and tools necessary to seamlessly implement and utilize Sign In with Apple functionality in their Python-based applications.
Prerequisite
This article is not focussing on how to get the value from Apple Developer page.
- Client ID (client_id)
- Client Secret (client_secret) - A JSON Web Token (JWT) generated by the developer
Generate client secret
Generate a signed token to identify your client application. [2]
key_id = None
team_id = None
client_id = None
private_key = None # .p8 key file
headers = {"kid": key_id}
open_private_key = open(private_key)
private_key_data = open_private_key.read()
payload = {
"iss": team_id,
"iat": datetime.now(),
"exp": datetime.now() + timedelta(days=180),
"aud": "https://appleid.apple.com",
"sub": client_id,
}
client_secret = jwt.encode(
payload, private_key_data, algorithm="ES256", headers=headers
).decode("utf-8")
Generate and validate tokens
Validate an authorization grant code originating from your frontend interface.
headers = {"content-type": "application/x-www-form-urlencoded"}
data = {
"client_id": client_id,
"client_secret": client_secret,
"code": id_token,
"grant_type": "authorization_code",
}
res = requests.post(URL, data=data, headers=headers)
values = res.json()
Below is the response you'll get after success make request
{
"access_token": "adg61...67Or9",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "rca7...lABoQ",
"id_token": "eyJra...96sZg"
}
- access_token: token from frontend
- token_type: type for OAuth 2.0 framework
- expires_in: lifespan or validity duration of an access token
- refresh_token: renews access without re-login
- id_token: token to get the user details (next action)
Get the user details
decoded = jwt.decode(
id_token,
"",
verify=False,
options={"verify_signature": False},
algorithms=["HS256"],
)
Top comments (2)
Love the article!
You might be interested why Apple token key is created that way (same as other OAuth patterns) - OIDC standard 👍
Thanks bro @alserembani
I'm slowly diving deeper into understanding JWT, OAuth2 and putting it into practice :)