import base64, binascii, hexdump, argparse, textwrap, uuid def guid_to_string(binary_guid): return str(uuid.UUID(bytes_le=binary_guid)).lower() def b64_d(string): return base64.b64decode(string + '=' * (-len(string) % 4)) def b64_url_d(string): return base64.urlsafe_b64decode(string + '=' * (-len(string) % 4)) if __name__ == '__main__': parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, description='', epilog=textwrap.dedent('''Examples:\npython3 parse.py --rh "1.AX[snip]95AA."\npython3 parse.py --refresh-token "1.AXkA[snip]95AA.AgABAw[snip]" ''') ) parser.add_argument('-rh','--rh', dest="rh", default=None, help="rh from parsed/described Access Token") parser.add_argument('-rt','--refresh-token', '--code', dest="refresh", default=None, help="Refresh Token or Code from oauth flow") args = parser.parse_args() if args.rh: rh = args.rh.split(".") print("Parsing rh (refresh header?)") print(f"Version: {rh[0]}") print(f"Preamble: {binascii.hexlify(b64_url_d(rh[1])[:3])}") tenant = b64_url_d(rh[1])[3:3+16] tenant = guid_to_string(tenant) print(f"Tenant ID: {tenant}") app = b64_url_d(rh[1])[3+16:3+16+16] app = guid_to_string(app) print(f"App ID: {app}") print(f"Postamble: {binascii.hexlify(b64_url_d(rh[1])[-5:])}") if args.refresh: refresh = args.refresh.split(".") rh = refresh[1] print("Parsing Refresh Token") print(f"Version: {refresh[0]}") print(f"Preamble: {binascii.hexlify(b64_url_d(rh)[:3])}") tenant = b64_url_d(rh)[3:3+16] tenant = guid_to_string(tenant) print(f"Tenant ID: {tenant}") app = b64_url_d(rh)[3+16:3+16+16] app = guid_to_string(app) print(f"App ID: {app}") print(f"Postamble: {binascii.hexlify(b64_url_d(rh)[-5:])}") a = b64_url_d(refresh[2])[:16] b = b64_url_d(refresh[2])[16:32] print(f"Possible type ID\n03=refresh_token, 04=oauth_code {guid_to_string(a)}") print(f"Possible key ID? {guid_to_string(b)}") print("Dumping encrypted part") hexdump.hexdump(b64_url_d(refresh[2])[32:])