// const http = require('http') // const fs = require('fs') // const {addSkirdaAccount} = require('configmanager') // const auth_api_url = 'http://192.168.88.10:8083' const auth_api_url = 'http://localhost:8083' // const auth_api_url = 'http://skirda-auth.brzezinski.ru' function uuidv4() { return '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, c => (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16) ) } class SkirdaDiscordAuth{ /** * @typedef {Object} DiscordRedirectAuth * @property {string} redirectUrl how the person is called * @property {string} requestId how many years the person lived * * @return {Promise} * */ static temp_installId = uuidv4() static async Init(){ const resp = await fetch(`${auth_api_url}/v1/auth/discord/init?installId=${SkirdaDiscordAuth.temp_installId}`) if (resp.statusCode !== 200){ return await resp.text() } return await resp.json() } /** * @param requestId {string} Request id from init route // * @param timeout {number} Timeout to poll in seconds * @return {SkirdaUserResp | string} Result of OAuth login */ static async CyclePolling(requestId){ for (let i = 0; i < 15; i++) { const resp = await SkirdaDiscordAuth._poll(requestId) switch (resp.status){ case 204: await SkirdaDiscordAuth._sleep(4000) continue case 200: return await resp.json() default: console.error(await resp.text()) return 'TODO error' } } } /** * @typedef {Object} SkYggAuthResponse * @property {string} ClientToken * @property {string} AccessToken * @property {YggProfile} Profile * * @typedef {Object} YggProfile * @property {string} name * @property {string} UUID * * @param jwtToken {string} JWT Token for auth * @return {YggProfile | string} Result of auth */ static async YggdrasilAuth(jwtToken){ const resp = await fetch(`${auth_api_url}/yggdrasil/skirda/authenticate`, { headers:{ 'Content-Type': 'application/json', 'Authorization': jwtToken } }) if (resp.statusCode !== 200){ return await resp.text() } return await resp.json() } /** * @typedef {Object} SkirdaUserResp * @property skirdaUserId {string} * @property username {string} * @property token {string} * * @param requestId {string} * @return {Response} * */ static async _poll(requestId){ const resp = await fetch(`${auth_api_url}/v1/auth/discord/periodicPolling?installId=${SkirdaDiscordAuth.temp_installId}&requestId=${requestId}`) return resp } static _sleepSetTimeout_ctrl /** * @param ms {number} * @return {boolean} */ static async _sleep(ms) { clearInterval(this._sleepSetTimeout_ctrl) return new Promise(resolve => this._sleepSetTimeout_ctrl = setTimeout(resolve, ms)) } static async ValidateAccount(jwtToken) { const resp = await fetch(`${auth_api_url}/v1/auth/refresh`,{ headers:{ 'Content-Type': 'application/json', 'Authorization': jwtToken } }) // console.log(resp, resp.statusCode) return resp.status === 200 } } // const skAuth = new SkirdaDiscordAuth() const loginSkirdaDiscordButton = document.getElementById('loginSkirdaDiscordInitAuth') /** * @return boolean * */ async function InitSkirdaDiscordLogin (){ const res = await SkirdaDiscordAuth.Init() let redir try { redir = JSON.parse(res) } catch (e) { SpawnError(Lang.queryJS('login.error.unknown')) return } // console.log(redir) const resOpenUrl = await shell.openExternal(redir.redirectUrl) const skirdaAuth = await SkirdaDiscordAuth.CyclePolling(redir.requestId) //TODO validate resp // console.log(skirdaAuth) if (typeof skirdaAuth.token !== 'string'){ SpawnError(Lang.queryJS('login.error.unknown')) return } const yggAuth = await SkirdaDiscordAuth.YggdrasilAuth(skirdaAuth.token) let yggAuthRes try { yggAuthRes = JSON.parse(yggAuth) } catch (e) { SpawnError(Lang.queryJS('login.error.unknown')) return } // console.log(yggAuthRes) AuthManager.addSkirdaAccount(yggAuthRes.profile.id, skirdaAuth.token, skirdaAuth.skirdaUserId, yggAuthRes.profile.name, skirdaAuth.token).then((value) => { updateSelectedAccount(value) }) setTimeout(() => { switchView(VIEWS.loginSkirdaDiscord, VIEWS.landing, 500, 500) }, 1000) } function SpawnError(actualDisplayableError){ setOverlayContent(actualDisplayableError.title, actualDisplayableError.desc, Lang.queryJS('login.tryAgain')) setOverlayHandler(() => { formDisabled(false) toggleOverlay(false) }) toggleOverlay(true) }