diff --git a/libraries/LocalUIApp.js b/libraries/LocalUIApp.js index 631ab3ca8..0aed9b526 100644 --- a/libraries/LocalUIApp.js +++ b/libraries/LocalUIApp.js @@ -2,7 +2,7 @@ const cors = require('cors'); const express = require('express'); const fs = require('fs'); const path = require('path'); -const toolboxEdgeProxyRequestHandler = require('./serverHelpers/toolboxEdgeProxyRequestHandler.js'); +const proxyRequestHandler = require('./serverHelpers/proxyRequestHandler.js'); const contentScriptDir = 'content_scripts'; const contentStyleDir = 'content_styles'; @@ -63,7 +63,7 @@ class LocalUIApp { } res.status(403).send('access prohibited to non-script non-style file'); }); - this.app.get('/proxy/*', toolboxEdgeProxyRequestHandler); + this.app.get('/proxy/*', proxyRequestHandler); if (this.userinterfacePath && fs.existsSync(this.userinterfacePath)) { this.app.use(express.static(this.userinterfacePath)); } else { diff --git a/libraries/objectDefaultFiles/object.js b/libraries/objectDefaultFiles/object.js index 65052c251..b3ecd5ee2 100755 --- a/libraries/objectDefaultFiles/object.js +++ b/libraries/objectDefaultFiles/object.js @@ -28,7 +28,7 @@ object: '', publicData: {}, modelViewMatrix: [], - serverIp: '127.0.0.1', + serverIp: 'localhost', serverPort: '8080', matrices: { modelView: [], @@ -747,6 +747,8 @@ this.analyticsSetSpaghettiVisible = makeSendStub('analyticsSetSpaghettiVisible'); this.analyticsSetAllClonesVisible = makeSendStub('analyticsSetAllClonesVisible'); + this.getOAuthToken = makeSendStub('getOAuthToken'); + // deprecated methods this.sendToBackground = makeSendStub('sendToBackground'); } @@ -1767,6 +1769,31 @@ }); }; + /** + * Makes an OAuth request at `authorizationUrl`, requires the OAuth flow to redirect to navigate:// + * Will not call `callback` on initial OAuth flow, as the whole app gets reloaded + * TODO: Write correct redirect URIs above + * @param {object} urls - OAuth Authorization and Access Token URL + * @param {string} clientId - OAuth client ID + * @param {string} clientSecret - OAuth client secret + * @param {function} callback - Callback function executed once OAuth flow completes + */ + this.getOAuthToken = function(urls, clientId, clientSecret, callback) { + postDataToParent({ + getOAuthToken: { + frame: spatialObject.frame, + clientId: clientId, + clientSecret: clientSecret, + urls + } + }); + spatialObject.messageCallBacks.onOAuthToken = function (msgContent) { + if (typeof msgContent.onOAuthToken !== 'undefined') { + callback(msgContent.onOAuthToken.token, msgContent.onOAuthToken.error); + } + }; + }; + this.getScreenshotBase64 = function(callback) { spatialObject.messageCallBacks.screenshotBase64 = function (msgContent) { if (typeof msgContent.screenshotBase64 !== 'undefined') { diff --git a/libraries/serverHelpers/oauthRequestHandlers.js b/libraries/serverHelpers/oauthRequestHandlers.js new file mode 100644 index 000000000..1ba6a524a --- /dev/null +++ b/libraries/serverHelpers/oauthRequestHandlers.js @@ -0,0 +1,54 @@ +const fetch = require('node-fetch'); +const querystring = require('querystring'); + +const oauthRefreshRequestHandler = (req, res) => { + const refreshUrl = req.params[0]; // TODO: get this from the tool somehow to prevent leaking secret to any supplied url + const data = { + 'grant_type': 'refresh_token', + 'refresh_token': req.body.refresh_token, + 'client_id': req.body.client_id, + 'client_secret': req.body.client_secret, + }; + fetch(refreshUrl, { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded' + }, + body: querystring.stringify(data) + }).then(response => { + return response.json(); + }).then(data => { + res.send(data); + }).catch(error => { + res.send(error); + }); +}; + +const oauthAcquireRequestHandler = (req, res) => { + const acquireUrl = req.params[0]; // TODO: get this from the addon somehow to prevent leaking secret to any client-supplied url (e.g. via postman) + const data = { + 'grant_type': 'authorization_code', + 'code': req.body.code, + 'redirect_uri': req.body.redirect_uri, + 'client_id': req.body.client_id, + 'client_secret': req.body.client_secret, + }; + fetch(acquireUrl, { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded' + }, + body: querystring.stringify(data) + }).then(response => { + return response.json(); + }).then(data => { + res.send(data); + }).catch(error => { + res.send(error); + }); +}; + +module.exports = { + oauthRefreshRequestHandler, + oauthAcquireRequestHandler +}; diff --git a/libraries/serverHelpers/proxyRequestHandler.js b/libraries/serverHelpers/proxyRequestHandler.js new file mode 100644 index 000000000..afadc0f9c --- /dev/null +++ b/libraries/serverHelpers/proxyRequestHandler.js @@ -0,0 +1,30 @@ +const https = require('https'); + +const proxyRequestHandler = (req, res) => { + const input = req.params[0]; + if (!input.includes('://')) { + const proxyURL = `https://toolboxedge.net/${req.params[0]}`; + const headers = req.headers; + headers.Host = "toolboxedge.net"; + https.get(proxyURL, {headers}, proxyRes => { + for (let header in proxyRes.headers) { + res.setHeader(header, proxyRes.headers[header]); + } + proxyRes.pipe(res); + }); + } else { + const proxyURL = req.params[0]; + const headers = req.headers; + headers.Host = new URL(proxyURL).host; + const queryParams = new URLSearchParams(req.query); + const url = `${proxyURL}?${queryParams.toString()}`; + https.get(url, {headers}, proxyRes => { + for (let header in proxyRes.headers) { + res.setHeader(header, proxyRes.headers[header]); + } + proxyRes.pipe(res); + }); + } +}; + +module.exports = proxyRequestHandler; diff --git a/libraries/serverHelpers/toolboxEdgeProxyRequestHandler.js b/libraries/serverHelpers/toolboxEdgeProxyRequestHandler.js deleted file mode 100644 index 6cee82fe2..000000000 --- a/libraries/serverHelpers/toolboxEdgeProxyRequestHandler.js +++ /dev/null @@ -1,15 +0,0 @@ -const https = require('https'); - -const toolboxEdgeProxyRequestHandler = (req, res) => { - const proxyURL = `https://toolboxedge.net/${req.params[0]}`; - const headers = req.headers; - headers.Host = "toolboxedge.net"; - https.get(proxyURL, {headers}, proxyRes => { - for (let header in proxyRes.headers) { - res.setHeader(header, proxyRes.headers[header]); - } - proxyRes.pipe(res); - }); -}; - -module.exports = toolboxEdgeProxyRequestHandler; diff --git a/server.js b/server.js index db1f916bb..cdb2a1021 100644 --- a/server.js +++ b/server.js @@ -194,9 +194,9 @@ services.getIP = function () { this.ips.interfaces = {}; // if this is mobile, only allow local interfaces if (isLightweightMobile || isStandaloneMobile) { - this.ips.interfaces['mobile'] = '127.0.0.1'; + this.ips.interfaces['mobile'] = 'localhost'; this.ips.activeInterface = 'mobile'; - return '127.0.0.1'; + return 'localhost'; } // Get All available interfaces @@ -216,7 +216,7 @@ services.getIP = function () { for (let key in interfaceNames) { let tempIps = this.networkInterface.toIps(interfaceNames[key], {ipVersion: 4}); - for (let key2 in tempIps) if (tempIps[key2] === '127.0.0.1') tempIps.splice(key2, 1); + tempIps = tempIps.filter(ip => !['127.0.0.1', 'localhost'].includes(ip)); this.ips.interfaces[interfaceNames[key]] = tempIps[0]; } @@ -588,6 +588,7 @@ const worldGraph = new WorldGraph(sceneGraph); const tempUuid = utilities.uuidTime().slice(1); // UUID of current run of the server (removed initial underscore) const HumanPoseFuser = require('./libraries/HumanPoseFuser'); +const {oauthRefreshRequestHandler} = require('./libraries/serverHelpers/oauthRequestHandlers.js'); const humanPoseFuser = new HumanPoseFuser(objects, sceneGraph, objectLookup, services.ip, version, protocol, beatPort, tempUuid); /********************************************************************************************************************** @@ -2061,8 +2062,12 @@ function objectWebServer() { }); // Proxies requests to toolboxedge.net, for CORS video playback - const toolboxEdgeProxyRequestHandler = require('./libraries/serverHelpers/toolboxEdgeProxyRequestHandler.js'); - webServer.get('/proxy/*', toolboxEdgeProxyRequestHandler); + const proxyRequestHandler = require('./libraries/serverHelpers/proxyRequestHandler.js'); + webServer.get('/proxy/*', proxyRequestHandler); + + const {oauthRefreshRequestHandler, oauthAcquireRequestHandler} = require('./libraries/serverHelpers/oauthRequestHandlers.js'); + webServer.post('/oauthRefresh/*', oauthRefreshRequestHandler); + webServer.post('/oauthAcquire/*', oauthAcquireRequestHandler); // restart the server from the web frontend to load webServer.get('/restartServer/', function () {