UNPKG

playactor

Version:

play around with your playstation devices

123 lines (122 loc) 5.9 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.OauthCredentialRequester = exports.registKeyToCredential = exports.extractAccountId = void 0; const debug_1 = __importDefault(require("debug")); const got_1 = __importDefault(require("got")); const protocol_1 = require("../../remoteplay/protocol"); const registration_1 = require("../../remoteplay/registration"); const redact_1 = require("../../util/redact"); const debug = debug_1.default("playactor:credentials:oauth"); // Remote Play Windows Client // TODO: it'd be nice to pull these for macOS and Linux so any // login history/notification will show the right platform const CLIENT_ID = "ba495a24-818c-472b-b12d-ff231c1b5745"; const CLIENT_SECRET = "mvaiZkRsAsI1IBkY"; const REDIRECT_URI = "https://remoteplay.dl.playstation.net/remoteplay/redirect"; const LOGIN_URL = `https://auth.api.sonyentertainmentnetwork.com/2.0/oauth/authorize?service_entity=urn:service-entity:psn&response_type=code&client_id=${CLIENT_ID}&redirect_uri=${REDIRECT_URI}&scope=psn:clientapp&request_locale=en_US&ui=pr&service_logo=ps&layout_type=popup&smcid=remoteplay&prompt=always&PlatformPrivacyWs1=minimal&`; const TOKEN_URL = "https://auth.api.sonyentertainmentnetwork.com/2.0/oauth/token"; function extractAccountId(accountInfo) { const asNumber = BigInt(accountInfo.user_id); const buffer = Buffer.alloc(8, "binary"); buffer.writeBigUInt64LE(asNumber); return buffer.toString("base64"); } exports.extractAccountId = extractAccountId; function registKeyToCredential(registKey) { // this is so bizarre, but here it is: // 1. Every 2 chars in data is interpreted as a hex byte const buffer = protocol_1.parseHexBytes(registKey); // 2. The bytes are treated as a utf-8-encoded string const asString = buffer.toString("utf-8"); // 3. That string is parsed as a hex-encoded long const asNumber = BigInt(`0x${asString}`); // Finally, we convert that back into a string for storage return asNumber.toString(); } exports.registKeyToCredential = registKeyToCredential; class OauthCredentialRequester { constructor(io, strategy) { this.io = io; this.strategy = strategy; } requestForDevice(device) { var _a; return __awaiter(this, void 0, void 0, function* () { const accountId = yield this.performOauth(); this.io.logInfo("Registering with device via Remote Play."); this.io.logInfo("Go to Settings > System > Remote Play > Link Device"); const pin = yield this.io.prompt("Enter PIN here> "); const registration = yield this.registerWithDevice(device, accountId, pin); const registKey = (_a = registration["PS5-RegistKey"]) !== null && _a !== void 0 ? _a : registration["PS4-RegistKey"]; if (!registKey) { throw new Error("Did not receive reigstration key"); } const credential = registKeyToCredential(registKey); return { "app-type": "r", "auth-type": "R", "client-type": "vr", model: "w", "user-credential": credential, accountId, registration, }; }); } performOauth() { return __awaiter(this, void 0, void 0, function* () { const redirected = yield this.strategy.performLogin(LOGIN_URL); const url = new URL(redirected); const code = url.searchParams.get("code"); if (!code) { throw new Error("Did not get OAuth Code"); } const accessToken = yield this.exchangeCodeForAccess(code); debug(`Fetched access token (${redact_1.redact(accessToken)}); requesting account info`); const accountInfo = yield got_1.default(`${TOKEN_URL}/${accessToken}`, { username: CLIENT_ID, password: CLIENT_SECRET, }).json(); return extractAccountId(accountInfo); }); } registerWithDevice(device, accountId, pin) { return __awaiter(this, void 0, void 0, function* () { const registration = new registration_1.RemotePlayRegistration(); return registration.register(device, { accountId, pin, }); }); } exchangeCodeForAccess(code) { return __awaiter(this, void 0, void 0, function* () { const { access_token: accessToken } = yield got_1.default.post(TOKEN_URL, { username: CLIENT_ID, password: CLIENT_SECRET, form: { code, grant_type: "authorization_code", redirect_uri: REDIRECT_URI, }, }).json(); if (!accessToken) { throw new Error("Did not receive OAuth access_token"); } return accessToken; }); } } exports.OauthCredentialRequester = OauthCredentialRequester;