DEV Community

Amzar
Amzar

Posted on

Guide to Validating Sign-In with Apple Tokens in Python

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.

  1. Client ID (client_id)
  2. 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")
Enter fullscreen mode Exit fullscreen mode

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()
Enter fullscreen mode Exit fullscreen mode

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"
}
Enter fullscreen mode Exit fullscreen mode
  1. access_token: token from frontend
  2. token_type: type for OAuth 2.0 framework
  3. expires_in: lifespan or validity duration of an access token
  4. refresh_token: renews access without re-login
  5. 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"],
            )
Enter fullscreen mode Exit fullscreen mode

References

  1. https://developer.apple.com/documentation/sign_in_with_apple/generate_and_validate_tokens
  2. https://developer.apple.com/documentation/accountorganizationaldatasharing/creating-a-client-secret

Top comments (2)

Collapse
 
alserembani profile image
Atif Aiman

Love the article!

You might be interested why Apple token key is created that way (same as other OAuth patterns) - OIDC standard πŸ‘

Collapse
 
amzar profile image
Amzar • Edited

Thanks bro @alserembani
I'm slowly diving deeper into understanding JWT, OAuth2 and putting it into practice :)