@@ -15,57 +15,60 @@ limitations under the License.
1515*/
1616
1717const { app} = require ( "electron" ) ;
18- const crypto = require ( "crypto" ) ;
18+ const path = require ( "path" ) ;
19+ const fs = require ( "fs" ) ;
1920
2021const 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
2328const 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
5448module . 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 } ,
0 commit comments