Verifying App Purchase with Apple Store Kit 2 and JWT in Python

Tiempo de lectura: < 1 minuto

We will share a function that will allow us to verify the purchases we make on Apple with Apple Store Kit 2 and JWT using Python.

Parapente - pexels

First, we will create a function utils that will allow us to validate the jwsRepresentation of the Apple purchase.

For that we will use these functions:

import base64import requestsimport jwtfrom cryptography.x509 import load_der_x509_certificatedef get_public_key_from_jws(jws_token):    # Decode only the header (without verification)    header_b64 = jws_token.split('.')[0]    header_json = base64.urlsafe_b64decode(pad_base64(header_b64))    import json    header = json.loads(header_json)    # Extract x5c if "x5c" not in header:    if "x5c" not in header:        raise ValueError("The JWS does not contain the header x5c")    cert_b64 = header["x5c"][0]    cert_der = base64.b64decode(cert_b64)    cert = load_der_x509_certificate(cert_der)    return cert.public_key()def verify_jws(jws_token):    try:        public_key = get_public_key_from_jws(jws_token)        payload = jwt.decode(            jws_token,             public_key,             algorithms=["ES256"],             options={"verify_aud": False} # Change to True if you verify 'aud'        )        return payload    except jwt.exceptions.InvalidSignatureError:        raise ValueError("Invalid signature")    except jwt.exceptions.ExpiredSignatureError:        raise ValueError("Token expired")    except Exception as e:        raise ValueError(f"Error verifying JWS: {str(e)}")def pad_base64(b64_string):    return b64_string + "=" * (-len(b64_string) % 4)

And its usage is like this:

try:    payload = verify_jws(jwsRepresentation)    print("Purchase verified, payload:")    print(payload)except ValueError as e:    print("Error:", e)raise HTTPException(status_code=400, detail=f"Invalid Apple purchase: {str(e)}")

Note: If you use Expo IAP, you can use

JWS Representation

Or

purchase.purchaseToken;

Leave a Comment