From bf4a3f40208c312c92b885417b1e0aa290671a72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=A4rkl?= Date: Sat, 12 Oct 2019 15:13:46 +0200 Subject: [PATCH] Add AccountID Script --- README.md | 8 ++++ scripts/psn-account-id.py | 92 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+) create mode 100755 scripts/psn-account-id.py diff --git a/README.md b/README.md index e1325cf..eb221ae 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,13 @@ cmake .. make ``` +## Obtaining your PSN AccountID + +Starting with PS4 7.0, it is necessary to use a so-called "AccountID" as opposed to the "Online-ID" for registration (streaming itself did not change). +This ID seems to be a unique identifier for a PSN Account and it can be obtained from the PSN after logging in using OAuth. +A Python 3 script which does this is provided in [scripts/psn-account-id.py](scripts/psn-account-id.py). +Simply run it in a terminal and follow the instructions. Once you know your ID, write it down. You will likely never have to do this process again. + ## Acknowledgements This project has only been made possible because of the following Open Source projects: @@ -52,6 +59,7 @@ This project has only been made possible because of the following Open Source pr [x64dbg](https://x64dbg.com/). Also thanks to [delroth](https://github.com/delroth) for analyzing the registration and wakeup protocol, +[grill2010](https://github.com/grill2010) for analyzing the PSN's OAuth Login, as well as a huge thank you to [FioraAeterna](https://github.com/FioraAeterna) for giving me some extremely helpful information about FEC and error correction. diff --git a/scripts/psn-account-id.py b/scripts/psn-account-id.py new file mode 100755 index 0000000..5c50cb7 --- /dev/null +++ b/scripts/psn-account-id.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import sys +if sys.version_info < (3, 0, 0): + print("DO NOT use Python 2.\nEVER.\nhttps://pythonclock.org") + exit(1) + +try: + import requests +except ImportError as e: + print(e) + print("\"requests\" is not available. Install it with pip whatever.") + exit(1) + +from urllib.parse import urlparse, parse_qs, quote, urljoin +import pprint +import base64 + +# Remote Play Windows Client +CLIENT_ID = "ba495a24-818c-472b-b12d-ff231c1b5745" +CLIENT_SECRET = "mvaiZkRsAsI1IBkY" + +LOGIN_URL = "https://auth.api.sonyentertainmentnetwork.com/2.0/oauth/authorize?service_entity=urn:service-entity:psn&response_type=code&client_id={}&redirect_uri=https://remoteplay.dl.playstation.net/remoteplay/redirect&scope=psn:clientapp&request_locale=en_US&ui=pr&service_logo=ps&layout_type=popup&smcid=remoteplay&prompt=always&PlatformPrivacyWs1=minimal&".format(CLIENT_ID) +TOKEN_URL = "https://auth.api.sonyentertainmentnetwork.com/2.0/oauth/token" + +print() +print("########################################################") +print(" Script to determine PSN AccountID") +print(" thanks to grill2010") +print(" (This script will perform network operations.)") +print("########################################################") +print() +print("➡️ Open the following URL in your Browser and log in:") +print() +print(LOGIN_URL) +print() +print("➡️ After logging in, when the page shows \"redirect\", copy the URL from the address bar and paste it here:") +code_url_s = input("> ") +code_url = urlparse(code_url_s) +query = parse_qs(code_url.query) +if "code" not in query or len(query["code"]) == 0 or len(query["code"][0]) == 0: + print("☠️ URL did not contain code parameter") + exit(1) +code = query["code"][0] + +print("🌏 Requesting OAuth Token") + +api_auth = requests.auth.HTTPBasicAuth(CLIENT_ID, CLIENT_SECRET) +body = "grant_type=authorization_code&code={}&redirect_uri=https://remoteplay.dl.playstation.net/remoteplay/redirect&".format(code) + +token_request = requests.post(TOKEN_URL, + auth = api_auth, + headers = { "Content-Type": "application/x-www-form-urlencoded" }, + data = body.encode("ascii")) + +print("⚠️ WARNING: From this point on, output might contain sensitive information in some cases!") + +if token_request.status_code != 200: + print("☠️ Request failed with code {}:\n{}".format(token_request.status_code, token_request.text)) + exit(1) + +token_json = token_request.json() +if "access_token" not in token_json: + print("☠️ \"access_token\" is missing in response JSON:\n{}".format(token_request.text)) + exit(1) +token = token_json["access_token"] + +print("🌏 Requesting Account Info") + +account_request = requests.get(TOKEN_URL + "/" + quote(token), + auth = api_auth) + +if account_request.status_code != 200: + print("☠️ Request failed with code {}:\n{}".format(account_request.status_code, account_request.text)) + exit(1) + +account_info = account_request.json() +print("🥦 Received Account Info:") +pprint.pprint(account_info) + +if "user_id" not in account_info: + print("☠️ \"user_id\" is missing in response or not a string") + exit(1) + +user_id = int(account_info["user_id"]) +user_id_base64 = base64.b64encode(user_id.to_bytes(8, "little")).decode() + +print() +print("🍙 This is your AccountID:") +print(user_id_base64) +