Skip to content

Commit 15bb819

Browse files
committed
Instead of encrypting, pass the HS an opaque token which we locally resolve in a map to our profile data
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
1 parent 4afd29f commit 15bb819

File tree

3 files changed

+40
-39
lines changed

3 files changed

+40
-39
lines changed

electron_app/src/electron-main.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ const tray = require('./tray');
3535
const vectorMenu = require('./vectormenu');
3636
const webContentsHandler = require('./webcontents-handler');
3737
const updater = require('./updater');
38-
const {getProfileFromDeeplink, protocolInit, getArgs} = require('./protocol');
38+
const {getProfileFromDeeplink, protocolInit, recordSSOSession} = require('./protocol');
3939

4040
const windowStateKeeper = require('electron-window-state');
4141
const Store = require('electron-store');
@@ -237,8 +237,8 @@ ipcMain.on('ipcCall', async function(ev, payload) {
237237
case 'getConfig':
238238
ret = vectorConfig;
239239
break;
240-
case 'getRiotDesktopSsoArgs':
241-
ret = getArgs(argv);
240+
case 'startSSOFlow':
241+
recordSSOSession(args[0]);
242242
break;
243243

244244
default:

electron_app/src/protocol.js

Lines changed: 32 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -15,57 +15,60 @@ limitations under the License.
1515
*/
1616

1717
const {app} = require("electron");
18-
const crypto = require("crypto");
18+
const path = require("path");
19+
const fs = require("fs");
1920

2021
const PROTOCOL = "riot://";
21-
const SEARCH_PARAM = "riot-desktop-args";
22+
const SEARCH_PARAM = "riot-desktop-ssoid";
23+
const STORE_FILE_NAME = "sso-sessions.json";
24+
25+
// we getPath userData before electron-main changes it, so this is the default value
26+
const storePath = path.join(app.getPath("userData"), STORE_FILE_NAME);
2227

2328
const processUrl = (url) => {
2429
if (!global.mainWindow) return;
2530
console.log("Handling link: ", url);
2631
global.mainWindow.loadURL(url.replace(PROTOCOL, "vector://"));
2732
};
2833

29-
// we encrypt anything that we expose to be passed back to our callback protocol
30-
// so that homeservers don't see our directory paths and have the ability to manipulate them.
31-
const algorithm = "aes-192-cbc";
32-
33-
const getKeyIv = () => ({
34-
key: crypto.scryptSync(app.getPath("exe"), "salt", 24),
35-
iv: Buffer.alloc(16, 0),
36-
});
37-
38-
const encrypt = (plaintext) => {
39-
const {key, iv} = getKeyIv();
40-
const cipher = crypto.createCipheriv(algorithm, key, iv);
41-
let ciphertext = cipher.update(plaintext, "utf8", "hex");
42-
ciphertext += cipher.final("hex");
43-
return ciphertext;
34+
const readStore = () => {
35+
try {
36+
const s = fs.readFileSync(storePath, { encoding: "utf8" });
37+
const o = JSON.parse(s);
38+
return typeof o === "object" ? o : {};
39+
} catch (e) {
40+
return {};
41+
}
4442
};
4543

46-
const decrypt = (ciphertext) => {
47-
const {key, iv} = getKeyIv();
48-
const decipher = crypto.createDecipheriv(algorithm, key, iv);
49-
let plaintext = decipher.update(ciphertext, "hex", "utf8");
50-
plaintext += decipher.final("utf8");
51-
return plaintext;
44+
const writeStore = (data) => {
45+
fs.writeFileSync(storePath, JSON.stringify(data));
5246
};
5347

5448
module.exports = {
55-
getArgs: (argv) => {
56-
if (argv['profile-dir'] || argv['profile']) {
57-
return encrypt(app.getPath('userData'));
49+
recordSSOSession: (sessionID) => {
50+
const userDataPath = app.getPath('userData');
51+
const store = readStore();
52+
for (const key in store) {
53+
// ensure each instance only has one (the latest) session ID to prevent the file growing unbounded
54+
if (store[key] === userDataPath) {
55+
delete store[key];
56+
break;
57+
}
5858
}
59+
store[sessionID] = userDataPath;
60+
writeStore(store);
5961
},
6062
getProfileFromDeeplink: (args) => {
6163
// check if we are passed a profile in the SSO callback url
6264
const deeplinkUrl = args.find(arg => arg.startsWith('riot://'));
6365
if (deeplinkUrl && deeplinkUrl.includes(SEARCH_PARAM)) {
6466
const parsedUrl = new URL(deeplinkUrl);
6567
if (parsedUrl.protocol === 'riot:') {
66-
const profile = parsedUrl.searchParams.get(SEARCH_PARAM);
67-
console.log("Forwarding to profile: ", profile);
68-
return decrypt(profile);
68+
const ssoID = parsedUrl.searchParams.get(SEARCH_PARAM);
69+
const store = readStore();
70+
console.log("Forwarding to profile: ", store[ssoID]);
71+
return store[ssoID];
6972
}
7073
}
7174
},

src/vector/platform/ElectronPlatform.js

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import Spinner from "matrix-react-sdk/src/components/views/elements/Spinner";
3232
import {Categories, Modifiers, registerShortcut} from "matrix-react-sdk/src/accessibility/KeyboardShortcuts";
3333
import {Key} from "matrix-react-sdk/src/Keyboard";
3434
import React from "react";
35+
import {randomString} from "matrix-js-sdk/src/randomstring";
3536

3637
const ipcRenderer = window.ipcRenderer;
3738
const isMac = navigator.platform.toUpperCase().includes('MAC');
@@ -229,10 +230,9 @@ export default class ElectronPlatform extends VectorBasePlatform {
229230
});
230231
}
231232

232-
// we assume this happens before any SSO actions occur but do not block.
233-
this._ipcCall('getRiotDesktopSsoArgs').then(riotDesktopSsoArgs => {
234-
this.riotDesktopSsoArgs = riotDesktopSsoArgs;
235-
});
233+
// this is the opaque token we pass to the HS which when we get it in our callback we can resolve to a profile
234+
this.ssoID = randomString(32);
235+
this._ipcCall("startSSOFlow", this.ssoID);
236236
}
237237

238238
async getConfig(): Promise<{}> {
@@ -429,9 +429,7 @@ export default class ElectronPlatform extends VectorBasePlatform {
429429
getSSOCallbackUrl(hsUrl: string, isUrl: string): URL {
430430
const url = super.getSSOCallbackUrl(hsUrl, isUrl);
431431
url.protocol = "riot";
432-
if (this.riotDesktopSsoArgs) {
433-
url.searchParams.set("riot-desktop-args", this.riotDesktopSsoArgs);
434-
}
432+
url.searchParams.set("riot-desktop-ssoid", this.ssoID);
435433
return url;
436434
}
437435

0 commit comments

Comments
 (0)