Skip to content

Commit f434ada

Browse files
committed
feat: auto sign in localhost
1 parent da0376d commit f434ada

File tree

4 files changed

+114
-10
lines changed

4 files changed

+114
-10
lines changed

src-node/index.js

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ const PHOENIX_FS_URL = `/PhoenixFS${randomNonce(8)}`;
9393
const PHOENIX_STATIC_SERVER_URL = `/Static${randomNonce(8)}`;
9494
const PHOENIX_NODE_URL = `/PhoenixNode${randomNonce(8)}`;
9595
const PHOENIX_LIVE_PREVIEW_COMM_URL = `/PreviewComm${randomNonce(8)}`;
96+
const PHOENIX_AUTO_AUTH_URL = `/AutoAuth${randomNonce(8)}`;
9697

9798
const savedConsoleLog = console.log;
9899

@@ -190,7 +191,8 @@ function processCommand(line) {
190191
phoenixFSURL: `ws://localhost:${port}${PHOENIX_FS_URL}`,
191192
phoenixNodeURL: `ws://localhost:${port}${PHOENIX_NODE_URL}`,
192193
staticServerURL: `http://localhost:${port}${PHOENIX_STATIC_SERVER_URL}`,
193-
livePreviewCommURL: `ws://localhost:${port}${PHOENIX_LIVE_PREVIEW_COMM_URL}`
194+
livePreviewCommURL: `ws://localhost:${port}${PHOENIX_LIVE_PREVIEW_COMM_URL}`,
195+
autoAuthURL: `http://localhost:${port}${PHOENIX_AUTO_AUTH_URL}`
194196
}, jsonCmd.commandID);
195197
});
196198
return;
@@ -207,6 +209,67 @@ rl.on('line', (line) => {
207209

208210
const localhostOnly = 'localhost';
209211

212+
const AUTH_CONNECTOR_ID = "ph_auth";
213+
const EVENT_CONNECTED = "connected";
214+
let verificationCode = null;
215+
async function setVerificationCode(code) {
216+
verificationCode = code;
217+
}
218+
const nodeConnector = NodeConnector.createNodeConnector(AUTH_CONNECTOR_ID, {
219+
setVerificationCode
220+
});
221+
222+
const ALLOWED_ORIGIN = 'https://account.phcode.io';
223+
function autoAuth(req, res) {
224+
const origin = req.headers.origin;
225+
// localhost dev of loginService is not allowed here to not leak to production. So autoAuth is not available in
226+
// dev builds.
227+
const isAllowedOrigin = !origin || (ALLOWED_ORIGIN === origin);
228+
if(!isAllowedOrigin){
229+
res.writeHead(403, { 'Content-Type': 'text/plain' });
230+
res.end('Forbidden origin');
231+
return;
232+
}
233+
if (req.method === 'OPTIONS') {
234+
res.setHeader('Access-Control-Allow-Origin', origin);
235+
res.setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS');
236+
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
237+
res.setHeader('Access-Control-Allow-Credentials', 'true');
238+
res.setHeader('Access-Control-Allow-Private-Network', 'true');
239+
res.writeHead(204);
240+
res.end();
241+
return;
242+
}
243+
// Remove '/AutoAuth<rand>' from the beginning of the URL and construct file path
244+
const url = new URL(req.url, `http://${req.headers.host}`);
245+
const cleanPath = url.pathname.replace(PHOENIX_AUTO_AUTH_URL, '');
246+
// Check if the request is for the autoVerifyCode endpoint
247+
if (cleanPath === `/autoVerifyCode` && req.method === 'GET') {
248+
origin && res.setHeader('Access-Control-Allow-Origin', origin);
249+
if(!verificationCode) {
250+
res.setHeader('Content-Type', 'text/plain');
251+
res.writeHead(404);
252+
res.end('Not Found');
253+
return;
254+
}
255+
res.setHeader('Access-Control-Allow-Credentials', 'true');
256+
res.setHeader('Access-Control-Allow-Private-Network', 'true');
257+
res.setHeader('Content-Type', 'application/json');
258+
res.end(JSON.stringify({ code: verificationCode }));
259+
verificationCode = null; // verification code is only returned once
260+
} else if (cleanPath === `/appVerified` && req.method === 'GET') {
261+
nodeConnector.triggerPeer(EVENT_CONNECTED, "ok");
262+
origin && res.setHeader('Access-Control-Allow-Origin', origin);
263+
res.setHeader('Access-Control-Allow-Credentials', 'true');
264+
res.setHeader('Access-Control-Allow-Private-Network', 'true');
265+
res.setHeader('Content-Type', 'application/json');
266+
res.end("ok");
267+
} else {
268+
res.writeHead(404, { 'Content-Type': 'text/plain' });
269+
res.end('Not Found');
270+
}
271+
}
272+
210273
// Create an HTTP server
211274
const server = http.createServer((req, res) => {
212275
if (req.url.startsWith(PHOENIX_STATIC_SERVER_URL)) {
@@ -249,7 +312,9 @@ const server = http.createServer((req, res) => {
249312
}
250313
});
251314

252-
} else {
315+
} else if (req.url.startsWith(PHOENIX_AUTO_AUTH_URL)) {
316+
return autoAuth(req, res);
317+
}else {
253318
res.writeHead(404, { 'Content-Type': 'text/plain' });
254319
res.end('Not Found');
255320
}
@@ -269,5 +334,6 @@ server.listen(0, localhostOnly, () => {
269334
savedConsoleLog(`Phoenix node tauri FS url is ws://localhost:${port}${PHOENIX_FS_URL}`);
270335
savedConsoleLog(`Phoenix node connector url is ws://localhost:${port}${PHOENIX_NODE_URL}`);
271336
savedConsoleLog(`Phoenix live preview comm url is ws://localhost:${port}${PHOENIX_LIVE_PREVIEW_COMM_URL}`);
337+
savedConsoleLog(`Phoenix AutoAuth url is ws://localhost:${port}${PHOENIX_AUTO_AUTH_URL}`);
272338
serverPortResolve(port);
273339
});

src/node-loader.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,13 @@
1818
*
1919
*/
2020

21-
/*global Phoenix, fs, logger*/
21+
/*global fs, logger*/
2222

2323
function nodeLoader() {
24+
const KernalModeTrust = window.KernalModeTrust;
25+
if(!KernalModeTrust){
26+
throw new Error("KernalModeTrust is not defined. Cannot boot nodeLoader without trust ring");
27+
}
2428
const nodeLoadstartTime = Date.now();
2529
const phcodeExecHandlerMap = {};
2630
const nodeConnectorIDMap = {};
@@ -721,6 +725,7 @@ function nodeLoader() {
721725
fs.setNodeWSEndpoint(message.phoenixFSURL);
722726
fs.forceUseNodeWSEndpoint(true);
723727
setNodeWSEndpoint(message.phoenixNodeURL);
728+
KernalModeTrust.localAutoAuthURL = message.autoAuthURL;
724729
window.isNodeReady = true;
725730
resolve(message);
726731
// node is designed such that it is not required at boot time to lower startup time.

src/services/login.js

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ define(function (require, exports, module) {
2626
NativeApp = require("utils/NativeApp"),
2727
ProfileMenu = require("./profile-menu"),
2828
Mustache = require("thirdparty/mustache/mustache"),
29+
NodeConnector = require("NodeConnector"),
2930
otpDialogTemplate = require("text!./html/otp-dialog.html");
3031

3132
const KernalModeTrust = window.KernalModeTrust;
@@ -52,6 +53,13 @@ define(function (require, exports, module) {
5253
exports.trigger(_EVT_PAGE_FOCUSED);
5354
});
5455

56+
const AUTH_CONNECTOR_ID = "ph_auth";
57+
const EVENT_CONNECTED = "connected";
58+
let authNodeConnector;
59+
if(Phoenix.isNativeApp) {
60+
authNodeConnector = NodeConnector.createNodeConnector(AUTH_CONNECTOR_ID, exports);
61+
}
62+
5563

5664
function isLoggedIn() {
5765
return isLoggedInUser;
@@ -148,9 +156,17 @@ define(function (require, exports, module) {
148156
// maybe some intermittent network error, ERR_RETRY_LATER is here. do nothing
149157
}
150158

159+
function _getAutoAuthPortURL() {
160+
const localAutoAuthURL = KernalModeTrust.localAutoAuthURL; // Eg: http://localhost:33577/AutoAuthDI0zAUJo
161+
if(!localAutoAuthURL) {
162+
return "9797/urlDoesntExist";
163+
}
164+
return localAutoAuthURL.replace("http://localhost:", "");
165+
}
166+
151167
// never rejects.
152168
async function _getAppAuthSession() {
153-
const authPortURL = "9797/abc"; // todo autho auth later
169+
const authPortURL = _getAutoAuthPortURL();
154170
const appName = encodeURIComponent(`${Strings.APP_NAME} Desktop on ${Phoenix.platform}`);
155171
const resolveURL = `${Phoenix.config.account_url}getAppAuthSession?autoAuthPort=${authPortURL}&appName=${appName}`;
156172
// {"isSuccess":true,"appSessionID":"a uuid...","validationCode":"SWXP07"}
@@ -171,6 +187,20 @@ define(function (require, exports, module) {
171187
}
172188
}
173189

190+
async function setAutoVerificationCode(validationCode) {
191+
const TIMEOUT_MS = 1000;
192+
try {
193+
await Promise.race([
194+
authNodeConnector.execPeer("setVerificationCode", validationCode),
195+
new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), TIMEOUT_MS))
196+
]);
197+
} catch (e) {
198+
console.error("failed to send auth login verification code to node", e);
199+
// we ignore this and continue for manual verification
200+
// todo raise metrics
201+
}
202+
}
203+
174204
async function signInToAccount() {
175205
if (!navigator.onLine) {
176206
Dialogs.showModalDialog(
@@ -190,6 +220,7 @@ define(function (require, exports, module) {
190220
return;
191221
}
192222
const {appSessionID, validationCode} = appAuthSession;
223+
await setAutoVerificationCode(validationCode);
193224
const appSignInURL = `${Phoenix.config.account_url}authorizeApp?appSessionID=${appSessionID}`;
194225

195226
// Show dialog with validation code
@@ -260,10 +291,15 @@ define(function (require, exports, module) {
260291
}
261292
}
262293
exports.on(_EVT_PAGE_FOCUSED, checkLoginStatus);
294+
async function _AutoSignedIn() {
295+
await checkLoginStatus();
296+
}
297+
authNodeConnector.one(EVENT_CONNECTED, _AutoSignedIn);
263298

264299
// Clean up when dialog is closed
265300
dialog.done(function() {
266301
exports.off(_EVT_PAGE_FOCUSED, checkLoginStatus);
302+
authNodeConnector.off(EVENT_CONNECTED, _AutoSignedIn);
267303
clearTimeout(closeTimeout);
268304
});
269305
NativeApp.openURLInDefaultBrowser(appSignInURL);

src/styles/UserProfile.less

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
overflow: hidden;
1010
position: absolute;
1111
z-index: @z-index-brackets-context-menu-base;
12-
animation: user-profile-dropdown-animation 90ms cubic-bezier(0, .97, .2, .99);
1312
transform-origin: 0 0;
1413

1514
.popup-header {
@@ -112,6 +111,9 @@
112111
text-align: left;
113112
padding: 8px 12px;
114113
margin: 3px 0;
114+
display: flex;
115+
justify-content: center;
116+
align-items: center;
115117

116118
i {
117119
margin-right: 8px;
@@ -279,8 +281,3 @@
279281
}
280282
}
281283
}
282-
283-
@keyframes user-profile-dropdown-animation {
284-
0% { opacity: 0.5; transform: translate3d(0, 0, 0) scale(0.5); }
285-
100% { opacity: 1; transform: translate3d(0, 0, 0) scale(1); }
286-
}

0 commit comments

Comments
 (0)