Compare commits

...

4 Commits

Author SHA1 Message Date
GeekCorner
af5147ceec
Merge 5fb312628a into e6cf76b436 2023-07-30 00:10:21 +03:00
GeekCorner
e6cf76b436
docs (Microsoft Auth): Add docs regarding whitelist system (#300)
* docs (Microsoft Auth): Add docs regarding whitelist system

* docs: Commit Dan's suggestion

Co-authored-by: Daniel Scalzi <d_scalzi@yahoo.com>

* docs: Commit Dan's second suggestion

Co-authored-by: Daniel Scalzi <d_scalzi@yahoo.com>

* docs: Commit Dan's third suggestion

Co-authored-by: Daniel Scalzi <d_scalzi@yahoo.com>

* docs: Commit Dan's fourth suggestion

Co-authored-by: Daniel Scalzi <d_scalzi@yahoo.com>

* docs: Commit Dan's fifth suggestion

Co-authored-by: Daniel Scalzi <d_scalzi@yahoo.com>

---------

Co-authored-by: Daniel Scalzi <d_scalzi@yahoo.com>
2023-07-26 13:18:57 -04:00
GeekCorner
5fb312628a
Merge branch 'master' into ms-login2.0 2023-03-22 16:24:14 +01:00
GeekCornerGH
a818628e46
feat: MS Login v2.0 2022-12-07 19:59:10 +01:00
5 changed files with 123 additions and 132 deletions

View File

@ -233,5 +233,4 @@ loginButton.addEventListener('click', () => {
})
toggleOverlay(true)
})
})
})

View File

@ -353,8 +353,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)
})
}
@ -383,7 +384,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]
@ -406,7 +408,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 {
@ -415,6 +417,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, async () => {
await prepareSettings()
@ -499,7 +502,7 @@ function bindAuthAccountLogOut(){
} else {
processLogOut(val, isLastAccount)
}
}
})
}
@ -519,6 +522,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 {
@ -529,16 +533,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)
}
}
}
@ -571,7 +575,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){
@ -582,7 +586,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)
}

View File

@ -2,7 +2,7 @@
<div id="waitingContent">
<div class="waitingSpinner"></div>
<div id="waitingTextContainer">
<h2>Waiting for Microsoft..</h2>
<h2 id="waitingText">Waiting for Microsoft..</h2>
</div>
</div>
</div>

View File

@ -18,18 +18,35 @@ Authenticating with Microsoft is fully supported by Helios Launcher.
- Select **Mobile and desktop applications**.
- Choose `https://login.microsoftonline.com/common/oauth2/nativeclient` as the **Redirect URI**.
- Select **Configure** to finish adding the platform.
8. Go to **Credentials & secrets**.
- Select **Client secrets**.
- Click **New client secret**.
- Set a description.
- Click **Add**.
- Don't copy the client secret, adding one is just a requirement from Microsoft.
8. Navigate back to **Overview**.
9. Copy **Application (client) ID**.
Reference: https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app
## Adding the Azure Client ID to Helios Launcher.
In `app/assets/js/ipcconstants.js` you'll find **`AZURE_CLIENT_ID`**. Set it to your application's id.
Note: Azure Client ID is NOT a secret value and **can** be stored in git. Reference: https://stackoverflow.com/questions/57306964/are-azure-active-directorys-tenantid-and-clientid-considered-secrets
Then relaunch your app, and login. You'll be greeted with an error message, because the app isn't whitelisted yet. Microsoft needs some activity on the app before whitelisting it. __Trying to log in before requesting whitelist is mandatory.__
## Requesting whitelisting from Microsoft
1. Ensure you have completed every step of this doc page.
2. Fill [this form](https://aka.ms/mce-reviewappid) with the required information. Remember this is a new appID for approval. You can find both the Client ID and the Tenant ID on the overview page in the Azure Portal.
3. Give Microsoft some time to review your app.
4. Once you have received Microsoft's approval, allow up to 24 hours for the changes to apply.
----
You can now authenticate with Microsoft through the launcher.
You can now authenticate with Microsoft through the launcher.
References:
- https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app
- https://help.minecraft.net/hc/en-us/articles/16254801392141

193
index.js
View File

@ -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
})