Files
chimera-Public/test/server/ch-0915-trophy-browser-auth.test.js

52 lines
2.9 KiB
JavaScript

'use strict';
const test = require('node:test');
const assert = require('node:assert/strict');
const { EventEmitter } = require('node:events');
const fs = require('node:fs');
const path = require('node:path');
const { allowedSonyUrl, createSonyBrowserAuthentication } = require('../../src/ipc/trophy-history');
class FakeWindow extends EventEmitter {
constructor(options) {
super(); this.options = options; this.destroyed = false; this.shown = false;
const contents = new EventEmitter();
contents.session = { fetch: async () => ({ ok: true, json: async () => ({ npsso: 'n'.repeat(64) }) }), clearStorageData: async () => { this.storageCleared = true; }, clearCache: async () => { this.cacheCleared = true; } };
contents.setWindowOpenHandler = handler => { this.openHandler = handler; };
this.webContents = contents;
FakeWindow.latest = this;
}
loadURL(url) { this.url = url; queueMicrotask(() => this.webContents.emit('did-finish-load')); return Promise.resolve(); }
show() { this.shown = true; }
isDestroyed() { return this.destroyed; }
destroy() { this.destroyed = true; this.emit('closed'); }
}
test('Sony browser authentication uses an ephemeral hardened window and clears it after token exchange', async () => {
let received = null;
const authenticate = createSonyBrowserAuthentication({ BrowserWindow: FakeWindow, parent: {}, timeoutMs: 1000, randomBytes: () => Buffer.alloc(12, 7), authenticate: async input => { received = input; return { configured: true }; } });
const result = await authenticate();
assert.equal(result.configured, true); assert.equal(result.temporaryBrowserDataCleared, true);
assert.equal(received.npsso, 'n'.repeat(64));
assert.equal(FakeWindow.latest.options.webPreferences.partition.startsWith('persist:'), false);
assert.equal(FakeWindow.latest.options.webPreferences.nodeIntegration, false);
assert.equal(FakeWindow.latest.options.webPreferences.contextIsolation, true);
assert.equal(FakeWindow.latest.storageCleared, true); assert.equal(FakeWindow.latest.cacheCleared, true);
});
test('browser authentication allowlists only HTTPS Sony and PlayStation origins', () => {
assert.equal(allowedSonyUrl('https://ca.account.sony.com/api/v1/ssocookie'), true);
assert.equal(allowedSonyUrl('https://www.playstation.com/'), true);
assert.equal(allowedSonyUrl('http://www.playstation.com/'), false);
assert.equal(allowedSonyUrl('https://playstation.com.attacker.example/'), false);
});
test('desktop registration exposes automated authentication but blocks it from the web bridge', () => {
const root = path.resolve(__dirname, '../..');
const main = fs.readFileSync(path.join(root, 'main.js'), 'utf8');
const preload = fs.readFileSync(path.join(root, 'preload.js'), 'utf8');
assert.match(main, /_registerTrophyHistory\(ipcMain/);
assert.match(main, /WEB_BLOCKED_CHANNELS[\s\S]*trophy:history-import:browser-authenticate/);
assert.match(preload, /trophyHistoryBrowserAuthenticate/);
});