From a818628e46cc257e00df3b490c9f7e7ed664bfe2 Mon Sep 17 00:00:00 2001 From: GeekCornerGH <45696571+GeekCornerGH@users.noreply.github.com> Date: Wed, 7 Dec 2022 19:59:10 +0100 Subject: [PATCH] feat: MS Login v2.0 --- app/assets/js/scripts/login.js | 3 +- app/assets/js/scripts/settings.js | 36 +++--- app/waiting.ejs | 2 +- index.js | 193 +++++++++++++----------------- 4 files changed, 104 insertions(+), 130 deletions(-) diff --git a/app/assets/js/scripts/login.js b/app/assets/js/scripts/login.js index 724f09c4d7..f91dc75b79 100644 --- a/app/assets/js/scripts/login.js +++ b/app/assets/js/scripts/login.js @@ -235,5 +235,4 @@ loginButton.addEventListener('click', () => { }) toggleOverlay(true) }) - -}) \ No newline at end of file +}) diff --git a/app/assets/js/scripts/settings.js b/app/assets/js/scripts/settings.js index e86de97b4d..b5d019cda4 100644 --- a/app/assets/js/scripts/settings.js +++ b/app/assets/js/scripts/settings.js @@ -333,8 +333,9 @@ document.getElementById('settingsAddMojangAccount').onclick = (e) => { // Bind the add microsoft account button. document.getElementById('settingsAddMicrosoftAccount').onclick = (e) => { + document.getElementById("waitingText").innerHTML = "Please login in the window that has just opened" switchView(getCurrentView(), VIEWS.waiting, 500, 500, () => { - ipcRenderer.send(MSFT_OPCODE.OPEN_LOGIN, VIEWS.settings, VIEWS.settings) + ipcRenderer.send(MSFT_OPCODE.OPEN_LOGIN, VIEWS.landing, VIEWS.settings) }) } @@ -363,7 +364,8 @@ ipcRenderer.on(MSFT_OPCODE.REPLY_LOGIN, (_, ...arguments_) => { }) toggleOverlay(true) }) - } else if(arguments_[0] === MSFT_REPLY_TYPE.SUCCESS) { + } else if (arguments_[0] === MSFT_REPLY_TYPE.SUCCESS) { + document.getElementById("waitingText").innerHTML = "Retrieving your account information from Microsoft" const queryMap = arguments_[1] const viewOnClose = arguments_[2] @@ -374,7 +376,7 @@ ipcRenderer.on(MSFT_OPCODE.REPLY_LOGIN, (_, ...arguments_) => { // This is probably if you messed up the app registration with Azure. console.log('Error getting authCode, is Azure application registered correctly?') console.log(error) - console.log(error_description) + console.log(errorDesc) console.log('Full query map', queryMap) let error = queryMap.error // Error might be 'access_denied' ? let errorDesc = queryMap.error_description @@ -386,7 +388,7 @@ ipcRenderer.on(MSFT_OPCODE.REPLY_LOGIN, (_, ...arguments_) => { setOverlayHandler(() => { toggleOverlay(false) }) - toggleOverlay(true) + if (errorDesc !== "The user has denied access to the scope requested by the client application.") toggleOverlay(true)//If the user clicks "Back" button and closes the window }) } else { @@ -395,6 +397,7 @@ ipcRenderer.on(MSFT_OPCODE.REPLY_LOGIN, (_, ...arguments_) => { const authCode = queryMap.code AuthManager.addMicrosoftAccount(authCode).then(value => { + document.getElementById("waitingText").innerHTML = "Finished" updateSelectedAccount(value) switchView(getCurrentView(), viewOnClose, 500, 500, () => { prepareSettings() @@ -479,7 +482,7 @@ function bindAuthAccountLogOut(){ } else { processLogOut(val, isLastAccount) } - + } }) } @@ -499,6 +502,7 @@ function processLogOut(val, isLastAccount){ if(targetAcc.type === 'microsoft') { msAccDomElementCache = parent switchView(getCurrentView(), VIEWS.waiting, 500, 500, () => { + document.getElementById("waitingText").innerHTML = "Removing your Microsoft account from the launcher" //We actually don't have to wait anything from Mirosoft ipcRenderer.send(MSFT_OPCODE.OPEN_LOGOUT, uuid, isLastAccount) }) } else { @@ -509,16 +513,16 @@ function processLogOut(val, isLastAccount){ updateSelectedAccount(selAcc) validateSelectedAccount() } - if(isLastAccount) { - loginOptionsCancelEnabled(false) - loginOptionsViewOnLoginSuccess = VIEWS.settings - loginOptionsViewOnLoginCancel = VIEWS.loginOptions - switchView(getCurrentView(), VIEWS.loginOptions) - } - }) - $(parent).fadeOut(250, () => { - parent.remove() + $(parent).fadeOut(250, () => { + parent.remove() + }) }) + if (isLastAccount) { + loginOptionsCancelEnabled(false) + loginOptionsViewOnLoginSuccess = VIEWS.landing + loginOptionsViewOnLoginCancel = VIEWS.loginOptions + switchView(getCurrentView(), VIEWS.loginOptions) + } } } @@ -551,7 +555,7 @@ ipcRenderer.on(MSFT_OPCODE.REPLY_LOGOUT, (_, ...arguments_) => { const prevSelAcc = ConfigManager.getSelectedAccount() msftLogoutLogger.info('Logout Successful. uuid:', uuid) - + AuthManager.removeMicrosoftAccount(uuid) .then(() => { if(!isLastAccount && uuid === prevSelAcc.uuid){ @@ -562,7 +566,7 @@ ipcRenderer.on(MSFT_OPCODE.REPLY_LOGOUT, (_, ...arguments_) => { } if(isLastAccount) { loginOptionsCancelEnabled(false) - loginOptionsViewOnLoginSuccess = VIEWS.settings + loginOptionsViewOnLoginSuccess = VIEWS.landing loginOptionsViewOnLoginCancel = VIEWS.loginOptions switchView(getCurrentView(), VIEWS.loginOptions) } diff --git a/app/waiting.ejs b/app/waiting.ejs index 11c7e4d2c8..a5e52b971e 100644 --- a/app/waiting.ejs +++ b/app/waiting.ejs @@ -2,7 +2,7 @@
-

Waiting for Microsoft..

+

Waiting for Microsoft..

\ No newline at end of file diff --git a/index.js b/index.js index 2439781232..5d56481053 100644 --- a/index.js +++ b/index.js @@ -105,116 +105,8 @@ ipcMain.handle(SHELL_OPCODE.TRASH_ITEM, async (event, ...args) => { app.disableHardwareAcceleration() -const REDIRECT_URI_PREFIX = 'https://login.microsoftonline.com/common/oauth2/nativeclient?' - -// Microsoft Auth Login -let msftAuthWindow -let msftAuthSuccess -let msftAuthViewSuccess -let msftAuthViewOnClose -ipcMain.on(MSFT_OPCODE.OPEN_LOGIN, (ipcEvent, ...arguments_) => { - if (msftAuthWindow) { - ipcEvent.reply(MSFT_OPCODE.REPLY_LOGIN, MSFT_REPLY_TYPE.ERROR, MSFT_ERROR.ALREADY_OPEN, msftAuthViewOnClose) - return - } - msftAuthSuccess = false - msftAuthViewSuccess = arguments_[0] - msftAuthViewOnClose = arguments_[1] - msftAuthWindow = new BrowserWindow({ - title: 'Microsoft Login', - backgroundColor: '#222222', - width: 520, - height: 600, - frame: true, - icon: getPlatformIcon('SealCircle') - }) - - msftAuthWindow.on('closed', () => { - msftAuthWindow = undefined - }) - - msftAuthWindow.on('close', () => { - if(!msftAuthSuccess) { - ipcEvent.reply(MSFT_OPCODE.REPLY_LOGIN, MSFT_REPLY_TYPE.ERROR, MSFT_ERROR.NOT_FINISHED, msftAuthViewOnClose) - } - }) - - msftAuthWindow.webContents.on('did-navigate', (_, uri) => { - if (uri.startsWith(REDIRECT_URI_PREFIX)) { - let queries = uri.substring(REDIRECT_URI_PREFIX.length).split('#', 1).toString().split('&') - let queryMap = {} - - queries.forEach(query => { - const [name, value] = query.split('=') - queryMap[name] = decodeURI(value) - }) - - ipcEvent.reply(MSFT_OPCODE.REPLY_LOGIN, MSFT_REPLY_TYPE.SUCCESS, queryMap, msftAuthViewSuccess) - - msftAuthSuccess = true - msftAuthWindow.close() - msftAuthWindow = null - } - }) - - msftAuthWindow.removeMenu() - msftAuthWindow.loadURL(`https://login.microsoftonline.com/consumers/oauth2/v2.0/authorize?prompt=select_account&client_id=${AZURE_CLIENT_ID}&response_type=code&scope=XboxLive.signin%20offline_access&redirect_uri=https://login.microsoftonline.com/common/oauth2/nativeclient`) -}) - -// Microsoft Auth Logout -let msftLogoutWindow -let msftLogoutSuccess -let msftLogoutSuccessSent -ipcMain.on(MSFT_OPCODE.OPEN_LOGOUT, (ipcEvent, uuid, isLastAccount) => { - if (msftLogoutWindow) { - ipcEvent.reply(MSFT_OPCODE.REPLY_LOGOUT, MSFT_REPLY_TYPE.ERROR, MSFT_ERROR.ALREADY_OPEN) - return - } - - msftLogoutSuccess = false - msftLogoutSuccessSent = false - msftLogoutWindow = new BrowserWindow({ - title: 'Microsoft Logout', - backgroundColor: '#222222', - width: 520, - height: 600, - frame: true, - icon: getPlatformIcon('SealCircle') - }) - - msftLogoutWindow.on('closed', () => { - msftLogoutWindow = undefined - }) - - msftLogoutWindow.on('close', () => { - if(!msftLogoutSuccess) { - ipcEvent.reply(MSFT_OPCODE.REPLY_LOGOUT, MSFT_REPLY_TYPE.ERROR, MSFT_ERROR.NOT_FINISHED) - } else if(!msftLogoutSuccessSent) { - msftLogoutSuccessSent = true - ipcEvent.reply(MSFT_OPCODE.REPLY_LOGOUT, MSFT_REPLY_TYPE.SUCCESS, uuid, isLastAccount) - } - }) - - msftLogoutWindow.webContents.on('did-navigate', (_, uri) => { - if(uri.startsWith('https://login.microsoftonline.com/common/oauth2/v2.0/logoutsession')) { - msftLogoutSuccess = true - setTimeout(() => { - if(!msftLogoutSuccessSent) { - msftLogoutSuccessSent = true - ipcEvent.reply(MSFT_OPCODE.REPLY_LOGOUT, MSFT_REPLY_TYPE.SUCCESS, uuid, isLastAccount) - } + - if(msftLogoutWindow) { - msftLogoutWindow.close() - msftLogoutWindow = null - } - }, 5000) - } - }) - - msftLogoutWindow.removeMenu() - msftLogoutWindow.loadURL('https://login.microsoftonline.com/common/oauth2/v2.0/logout') -}) // Keep a global reference of the window object, if you don't, the window will // be closed automatically when the JavaScript object is garbage collected. @@ -223,8 +115,8 @@ let win function createWindow() { win = new BrowserWindow({ - width: 980, - height: 552, + width: 1143, + height: 700, icon: getPlatformIcon('SealCircle'), frame: false, webPreferences: { @@ -350,4 +242,83 @@ app.on('activate', () => { if (win === null) { createWindow() } +}) + +const REDIRECT_URI_PREFIX = 'https://login.microsoftonline.com/common/oauth2/nativeclient?' + +// Microsoft Auth Login +let msftAuthWindow +let msftAuthSuccess +let msftAuthViewSuccess +let msftAuthViewOnClose +ipcMain.on(MSFT_OPCODE.OPEN_LOGIN, (ipcEvent, ...arguments_) => { + /* + Clear cookies from live.com and github.com from Microsoft Login, since there isn't an actual way to invalidate Microsoft access token + */ + session.defaultSession.cookies.get({ domain: 'live.com' }).then((cookies) => { + for (let cookie of cookies) { + let urlcookie = `http${cookie.secure ? "s" : ""}://${cookie.domain.replace(/$\./, "") + cookie.path}`; + session.defaultSession.cookies.remove(urlcookie, cookie.name) + } + }) + session.defaultSession.cookies.get({ domain: 'github.com' }).then((cookies) => { + for (let cookie of cookies) { + let urlcookie = `http${cookie.secure ? "s" : ""}://${cookie.domain.replace(/$\./, "") + cookie.path}`; + session.defaultSession.cookies.remove(urlcookie, cookie.name) + } + }) + if (msftAuthWindow) { + ipcEvent.reply(MSFT_OPCODE.REPLY_LOGIN, MSFT_REPLY_TYPE.ERROR, MSFT_ERROR.ALREADY_OPEN, msftAuthViewOnClose) + return + } + msftAuthSuccess = false + msftAuthViewSuccess = arguments_[0] + msftAuthViewOnClose = arguments_[1] + msftAuthWindow = new BrowserWindow({ + parent: win, + modal: true, + resizable: false, + title: 'Microsoft Login', + backgroundColor: '#222222', + width: 520, + height: 700, + frame: true, + icon: getPlatformIcon('SealCircle') + }) + + msftAuthWindow.on('closed', () => { + msftAuthWindow = undefined + }) + + msftAuthWindow.on('close', () => { + if (!msftAuthSuccess) { + ipcEvent.reply(MSFT_OPCODE.REPLY_LOGIN, MSFT_REPLY_TYPE.ERROR, MSFT_ERROR.NOT_FINISHED, msftAuthViewOnClose) + } + }) + + msftAuthWindow.webContents.on('did-navigate', (_, uri) => { + if (uri.startsWith(REDIRECT_URI_PREFIX)) { + let queries = uri.substring(REDIRECT_URI_PREFIX.length).split('#', 1).toString().split('&') + let queryMap = {} + + queries.forEach(query => { + const [name, value] = query.split('=') + queryMap[name] = decodeURI(value) + }) + + ipcEvent.reply(MSFT_OPCODE.REPLY_LOGIN, MSFT_REPLY_TYPE.SUCCESS, queryMap, msftAuthViewSuccess) + + msftAuthSuccess = true + msftAuthWindow.close() + msftAuthWindow = null + } + }) + + msftAuthWindow.removeMenu() + msftAuthWindow.loadURL(`https://login.live.com/oauth20_authorize.srf?prompt=select_account&client_id=${AZURE_CLIENT_ID}&response_type=code&scope=XboxLive.signin%20offline_access&redirect_uri=https://login.microsoftonline.com/common/oauth2/nativeclient&cobrandid=8058f65d-ce06-4c30-9559-473c9275a65d`) //Cobrandid adds the Minecraft branding on the login page +}) + +// Microsoft Auth Logout +ipcMain.on(MSFT_OPCODE.OPEN_LOGOUT, (ipcEvent, uuid, isLastAccount) => { + ipcEvent.reply(MSFT_OPCODE.REPLY_LOGOUT, MSFT_REPLY_TYPE.SUCCESS, uuid, isLastAccount) //Just reply to the event, since logout pop up isn't that much useful }) \ No newline at end of file