diff --git a/app/waiting.ejs b/app/waiting.ejs
new file mode 100644
index 0000000..11c7e4d
--- /dev/null
+++ b/app/waiting.ejs
@@ -0,0 +1,8 @@
+
+
+
+
+
Waiting for Microsoft..
+
+
+
\ No newline at end of file
diff --git a/docs/MicrosoftAuth.md b/docs/MicrosoftAuth.md
new file mode 100644
index 0000000..589a75b
--- /dev/null
+++ b/docs/MicrosoftAuth.md
@@ -0,0 +1,35 @@
+# Microsoft Authentication
+
+Authenticating with Microsoft is fully supported by Helios Launcher.
+
+## Acquiring an Azure Client ID
+
+1. Navigate to https://portal.azure.com
+2. In the search bar, search for **Azure Active Directory**.
+3. In Azure Active Directory, go to **App Registrations** on the left pane (Under *Manage*).
+4. Click **New Registration**.
+ - Set **Name** to be your launcher's name.
+ - Set **Supported account types** to *Accounts in any organizational directory (Any Azure AD directory - Multitenant) and personal Microsoft accounts (e.g. Skype, Xbox)*
+ - Leave **Redirect URI** blank.
+ - Register the application.
+5. You should be on the application's management page. If not, Navigate back to **App Registrations**. Select the application you just registered.
+6. Click **Authentication** on the left pane (Under *Manage*).
+7. Click **Add Platform**.
+ - 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. 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
+
+----
+
+You can now authenticate with Microsoft through the launcher.
\ No newline at end of file
diff --git a/index.js b/index.js
index 08d6be3..91120ee 100644
--- a/index.js
+++ b/index.js
@@ -3,13 +3,14 @@ remoteMain.initialize()
// Requirements
const { app, BrowserWindow, ipcMain, Menu } = require('electron')
-const autoUpdater = require('electron-updater').autoUpdater
-const ejse = require('ejs-electron')
-const fs = require('fs')
-const isDev = require('./app/assets/js/isdev')
-const path = require('path')
-const semver = require('semver')
-const { pathToFileURL } = require('url')
+const autoUpdater = require('electron-updater').autoUpdater
+const ejse = require('ejs-electron')
+const fs = require('fs')
+const isDev = require('./app/assets/js/isdev')
+const path = require('path')
+const semver = require('semver')
+const { pathToFileURL } = require('url')
+const { AZURE_CLIENT_ID, MSFT_OPCODE, MSFT_REPLY_TYPE, MSFT_ERROR } = require('./app/assets/js/ipcconstants')
// Setup auto updater.
function initAutoUpdater(event, data) {
@@ -88,6 +89,118 @@ ipcMain.on('distributionIndexDone', (event, res) => {
// https://electronjs.org/docs/tutorial/offscreen-rendering
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.
let win
diff --git a/package-lock.json b/package-lock.json
index 9bf429f..e84b8f5 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -19,7 +19,7 @@
"fs-extra": "^10.0.0",
"github-syntax-dark": "^0.5.0",
"got": "^11.8.3",
- "helios-core": "^0.1.0-alpha.5",
+ "helios-core": "~0.1.0",
"jquery": "^3.6.0",
"node-stream-zip": "^1.15.0",
"request": "^2.88.2",
@@ -2308,9 +2308,9 @@
}
},
"node_modules/helios-core": {
- "version": "0.1.0-alpha.5",
- "resolved": "https://registry.npmjs.org/helios-core/-/helios-core-0.1.0-alpha.5.tgz",
- "integrity": "sha512-Ml6XNOg3lVmGXpvi3N+my01JW1QkzeghT5oQ3yU0Cby7R1az6z1kuz5UN2VuQpzsFeQtgqeTmDPQDOlXdvw9Nw==",
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/helios-core/-/helios-core-0.1.0.tgz",
+ "integrity": "sha512-p2jmVSeciR9wcKLPc5seMxU0YsURF8ttLAIJS1CHU5fyoe40F3GXWPhsSdbGiDSRjLUcOzpjea1WTyGJ0zAgEA==",
"dependencies": {
"fs-extra": "^10.0.0",
"got": "^11.8.3",
@@ -6376,9 +6376,9 @@
"dev": true
},
"helios-core": {
- "version": "0.1.0-alpha.5",
- "resolved": "https://registry.npmjs.org/helios-core/-/helios-core-0.1.0-alpha.5.tgz",
- "integrity": "sha512-Ml6XNOg3lVmGXpvi3N+my01JW1QkzeghT5oQ3yU0Cby7R1az6z1kuz5UN2VuQpzsFeQtgqeTmDPQDOlXdvw9Nw==",
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/helios-core/-/helios-core-0.1.0.tgz",
+ "integrity": "sha512-p2jmVSeciR9wcKLPc5seMxU0YsURF8ttLAIJS1CHU5fyoe40F3GXWPhsSdbGiDSRjLUcOzpjea1WTyGJ0zAgEA==",
"requires": {
"fs-extra": "^10.0.0",
"got": "^11.8.3",
diff --git a/package.json b/package.json
index 547268c..404004f 100644
--- a/package.json
+++ b/package.json
@@ -33,7 +33,7 @@
"fs-extra": "^10.0.0",
"github-syntax-dark": "^0.5.0",
"got": "^11.8.3",
- "helios-core": "^0.1.0-alpha.5",
+ "helios-core": "~0.1.0",
"jquery": "^3.6.0",
"node-stream-zip": "^1.15.0",
"request": "^2.88.2",