diff --git a/AuthKey_JZC9L76TDT.p8 b/AuthKey_JZC9L76TDT.p8 index b74bd74..a421871 100644 --- a/AuthKey_JZC9L76TDT.p8 +++ b/AuthKey_JZC9L76TDT.p8 @@ -3,4 +3,4 @@ MIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgOzAYvVe2plgEO65I rzpfDiorOSshVWOZyYyYxKukiMOgCgYIKoZIzj0DAQehRANCAATr5XT5byC/B3CD 3k5HZAVkcgnIpGIhLn/zcSoINnHpNoykKfNRcPAViyF5oPapP6dzdhzfXpPAschh eKfajgao ------END PRIVATE KEY----- \ No newline at end of file +-----END PRIVATE KEY----- diff --git a/jwt_signed.txt b/jwt_signed.txt index 8774798..32f91fb 100644 --- a/jwt_signed.txt +++ b/jwt_signed.txt @@ -1 +1 @@ -eyJhbGciOiJFUzI1NiIsImtpZCI6IkpaQzlMNzZURFQiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiI2OWE2ZGU4My0wMmYyLTQ3ZTMtZTA1My01YjhjN2MxMWE0ZDEiLCJpYXQiOjE3MDUzMjU5OTcsImV4cCI6MTcwNTMyOTI5NywiYXVkIjoiYXBwc3RvcmVjb25uZWN0LXYxIiwiYmlkIjoic3RheC5TbGFzaFBva2VyLm5vc2VibGVlZCJ9.Vr1p1t42RS6JC99USVHo1feS-43LeCGnBU464sa2fWFH-DaxAG8p6IeH3SfXoKAnN9UVJKF2ZOWkHypzJoFXSg \ No newline at end of file +eyJhbGciOiJFUzI1NiIsImtpZCI6IkpaQzlMNzZURFQiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiI2OWE2ZGU4My0wMmYyLTQ3ZTMtZTA1My01YjhjN2MxMWE0ZDEiLCJpYXQiOjE3MDUzMjk3MzIsImV4cCI6MTcwNTMzMzI3MiwiYXVkIjoiYXBwc3RvcmVjb25uZWN0LXYxIiwiYmlkIjoic3RheC5TbGFzaFBva2VyLm5vc2VibGVlZCJ9.qk7ncK1WBIZqLkFkEQkEknmd6TgpEdg5h7OflcFxc3VfE99wo6hQV33S4oXe-pw3Zyz2h3_uOlXY5spz3pl4nw \ No newline at end of file diff --git a/pokeranalytics_backend/settings.py b/pokeranalytics_backend/settings.py index 9049cae..52cb0f6 100644 --- a/pokeranalytics_backend/settings.py +++ b/pokeranalytics_backend/settings.py @@ -22,7 +22,7 @@ BASE_DIR = Path(__file__).resolve().parent.parent # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = 'django-insecure-v9l*b^t^2eqp877kdrt%5g#y=8$e%e^sa!65(1@t+rp@avwx+@' -ASS_KEY_FILE = BASE_DIR / 'AuthKey_JZC9L76TDT.p8' +ASS_KEY_FILE = BASE_DIR / 'AppleRootCA-G3.cer' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True diff --git a/subscriptions/AppleRootCA-G3.cer b/subscriptions/AppleRootCA-G3.cer new file mode 100644 index 0000000..228bfa3 Binary files /dev/null and b/subscriptions/AppleRootCA-G3.cer differ diff --git a/subscriptions/views.py b/subscriptions/views.py index aa76699..1eed61e 100644 --- a/subscriptions/views.py +++ b/subscriptions/views.py @@ -6,16 +6,24 @@ from django.conf import settings import json, jwt import base64 -import logging -import logging.config - -logger = logging.getLogger("main") +from OpenSSL.crypto import ( + X509Store, + X509StoreContext, + X509StoreContextError, + load_certificate, + FILETYPE_ASN1, + FILETYPE_PEM +) def index(request): return HttpResponse("Hello, world. You're at the subs index.") def test(request): - return HttpResponse("Test succeeded!") + KEY_FILE = settings.ASS_KEY_FILE + + with open(KEY_FILE,'r') as key_file: + key = ''.join(key_file.readlines()) + return HttpResponse(key) @csrf_exempt def app_store_webhook(request): @@ -26,24 +34,51 @@ def app_store_webhook(request): signedPayload = fulljson['signedPayload'] - content = signedPayload.split('.')[1] - jws_payload = base64.b64decode(content) - data = json.loads(jws_payload.decode()) + KEY_FILE = settings.ASS_KEY_FILE + with open(KEY_FILE,'r') as key_file: + key = ''.join(key_file.readlines()) - #KEY_FILE = settings.ASS_KEY_FILE + decodedPayload = _decode_jws(token, algorithms=algorithms) - #with open(KEY_FILE,'r') as key_file: - # key = ''.join(key_file.readlines()) - #decodedPayload = jwt.decode(signedPayload, key, algorithms=['ES256']) + # decodedPayload = jwt.decode(signedPayload, key, algorithms=['ES256']) #print('hell yeah!' + str(key)) #logger.debug('test getLogger' + str(key)) notification = ASSNotification( - content=jws_payload, + content=decodedPayload, ) notification.save() return JsonResponse({'status': 'success'}) + + +def _decode_jws(token, root_cert_path, algorithms): + try: + header = jwt.get_unverified_header(token) + + # the first cert contains the public key used to sign the jwt + first_cert_data = header["x5c"][0] + first_cert_data = add_labels(first_cert_data) + first_cert = load_certificate(FILETYPE_PEM, first_cert_data) + + # the other certs are an x5c (X.509 certificate chain) + chain_datas = header["x5c"][1:] + chain_datas = [add_labels(cd) for cd in chain_datas] + chain = [load_certificate(FILETYPE_PEM, cd) for cd in chain_datas] + + public_key = first_cert.get_pubkey().to_cryptography_key() + + store = X509Store() + store.add_cert(_get_root_cert(root_cert_path)) + ctx = X509StoreContext(store=store, certificate=first_cert, chain=chain) + ctx.verify_certificate() + + return jwt.decode(token, public_key, algorithms=algorithms) + except (ValueError, KeyError, jwt.exceptions.PyJWTError, X509StoreContextError) as err: + raise InvalidTokenError from err + +def add_labels(key: str) -> bytes: + return ("-----BEGIN CERTIFICATE-----\n" + key + "\n-----END CERTIFICATE-----").encode() diff --git a/token_generator.py b/token_generator.py index ccce487..e363d92 100644 --- a/token_generator.py +++ b/token_generator.py @@ -11,7 +11,7 @@ bid = 'stax.SlashPoker.nosebleed' # Define issue timestamp. issued_at_timestamp = int(dt.datetime.now().timestamp()) # Define expiration timestamp. May not exceed 20 minutes from issue timestamp. -expiration_timestamp = issued_at_timestamp + 55*60 +expiration_timestamp = issued_at_timestamp + 59*60 # Define JWT headers. headers = dict() @@ -43,7 +43,7 @@ key=key with open('jwt_signed.txt', 'w') as output: output.write(client_secret) -# curl -X POST -v -H 'Authorization: Bearer eyJhbGciOiJFUzI1NiIsImtpZCI6IkpaQzlMNzZURFQiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiI2OWE2ZGU4My0wMmYyLTQ3ZTMtZTA1My01YjhjN2MxMWE0ZDEiLCJpYXQiOjE3MDUzMjIxMjUsImV4cCI6MTcwNTMyNTQyNSwiYXVkIjoiYXBwc3RvcmVjb25uZWN0LXYxIiwiYmlkIjoic3RheC5TbGFzaFBva2VyLm5vc2VibGVlZCJ9.dM2cM92BX7f4f8fuF72HRaOutK1POs6tQcVriXMQQIA_tA_HOayXYuTRt_cUc4HLqErkRj9NNiT0CV0ZJECqpQ' https://api.storekit-sandbox.itunes.apple.com/inApps/v1/notifications/test +# curl -X POST -v -H 'Authorization: Bearer eyJhbGciOiJFUzI1NiIsImtpZCI6IkpaQzlMNzZURFQiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiI2OWE2ZGU4My0wMmYyLTQ3ZTMtZTA1My01YjhjN2MxMWE0ZDEiLCJpYXQiOjE3MDUzMjk3MzIsImV4cCI6MTcwNTMzMzI3MiwiYXVkIjoiYXBwc3RvcmVjb25uZWN0LXYxIiwiYmlkIjoic3RheC5TbGFzaFBva2VyLm5vc2VibGVlZCJ9.qk7ncK1WBIZqLkFkEQkEknmd6TgpEdg5h7OflcFxc3VfE99wo6hQV33S4oXe-pw3Zyz2h3_uOlXY5spz3pl4nw' https://api.storekit-sandbox.itunes.apple.com/inApps/v1/notifications/test # Usage, after run this code by python3 # get token from `client_secret.txt` and replace to [signed token] # Remember expired time maximum is 20 minutes