Răsfoiți Sursa

fix: use webRequest to intercept tokens (#1344)

...and block the request so redirect_uri doesn't see the token
tophf 4 ani în urmă
părinte
comite
21cf7f7583

+ 28 - 8
src/background/sync/base.js

@@ -548,23 +548,17 @@ function syncOne(service) {
   if (service.authState.is(['idle', 'error'])) return service.checkSync();
   if (service.authState.is('authorized')) return service.startSync();
 }
+
 export function sync() {
   const service = getService();
   return service && Promise.resolve(syncOne(service)).then(autoSync);
 }
 
-export function checkAuthUrl(url) {
-  return serviceNames.some((name) => {
-    const service = services[name];
-    const authorized = service.checkAuth && service.checkAuth(url);
-    return authorized;
-  });
-}
-
 export function authorize() {
   const service = getService();
   if (service) service.authorize();
 }
+
 export function revoke() {
   const service = getService();
   if (service) service.revoke();
@@ -578,6 +572,32 @@ export function setConfig(config) {
   }
 }
 
+export async function openAuthPage(url, redirectUri) {
+  unregisterWebRequest(); // otherwise our new tabId will be ignored
+  browser.webRequest.onBeforeRequest.addListener(onBeforeRequest, {
+    urls: [`${redirectUri}*`],
+    types: ['main_frame'],
+    tabId: (await browser.tabs.create({ url })).id,
+  }, ['blocking']);
+}
+
+/**
+ * @param {chrome.webRequest.WebResponseDetails} info
+ * @returns {chrome.webRequest.BlockingResponse}
+ */
+function onBeforeRequest(info) {
+  if (getService().checkAuth?.(info.url)) {
+    browser.tabs.remove(info.tabId);
+    // If we unregister without setTimeout, API will ignore { cancel: true }
+    setTimeout(unregisterWebRequest, 0);
+    return { cancel: true };
+  }
+}
+
+function unregisterWebRequest() {
+  browser.webRequest.onBeforeRequest.removeListener(onBeforeRequest);
+}
+
 hookOptions((data) => {
   const value = data?.['sync.current'];
   if (value) initialize();

+ 2 - 1
src/background/sync/dropbox.js

@@ -1,6 +1,7 @@
 import { loadQuery, dumpQuery } from '../utils';
 import {
   getURI, getItemFilename, BaseService, isScriptFile, register,
+  openAuthPage,
 } from './base';
 
 const config = {
@@ -100,7 +101,7 @@ const Dropbox = BaseService.extend({
       redirect_uri: config.redirect_uri,
     };
     const url = `https://www.dropbox.com/oauth2/authorize?${dumpQuery(params)}`;
-    browser.tabs.create({ url });
+    openAuthPage(url, config.redirect_uri);
   },
   authorized(raw) {
     const data = loadQuery(raw);

+ 2 - 1
src/background/sync/googledrive.js

@@ -6,6 +6,7 @@ import { objectGet } from '#/common/object';
 import { dumpQuery, notify } from '../utils';
 import {
   getURI, getItemFilename, BaseService, register, isScriptFile,
+  openAuthPage,
 } from './base';
 
 const SECRET_KEY = JSON.parse(window.atob('eyJjbGllbnRfc2VjcmV0IjoiTjBEbTZJOEV3bkJaeE1xMUpuMHN3UER0In0='));
@@ -118,7 +119,7 @@ const GoogleDrive = BaseService.extend({
     };
     if (!this.config.get('refresh_token')) params.prompt = 'consent';
     const url = `https://accounts.google.com/o/oauth2/v2/auth?${dumpQuery(params)}`;
-    browser.tabs.create({ url });
+    openAuthPage(url, config.redirect_uri);
   },
   checkAuth(url) {
     const redirectUri = `${config.redirect_uri}?code=`;

+ 0 - 5
src/background/sync/index.js

@@ -1,5 +1,4 @@
 import {
-  checkAuthUrl,
   initialize,
   sync,
   getStates,
@@ -20,10 +19,6 @@ Object.assign(commands, {
   SyncSetConfig: setConfig,
 });
 
-browser.tabs.onUpdated.addListener((tabId, changes) => {
-  if (changes.url && checkAuthUrl(changes.url)) browser.tabs.remove(tabId);
-});
-
 export {
   initialize,
   sync,

+ 2 - 1
src/background/sync/onedrive.js

@@ -4,6 +4,7 @@ import { objectGet } from '#/common/object';
 import { dumpQuery } from '../utils';
 import {
   getURI, getItemFilename, BaseService, isScriptFile, register,
+  openAuthPage,
 } from './base';
 
 const SECRET_KEY = JSON.parse(window.atob('eyJjbGllbnRfc2VjcmV0Ijoiajl4M09WRXRIdmhpSEtEV09HcXV5TWZaS2s5NjA0MEgifQ=='));
@@ -106,7 +107,7 @@ const OneDrive = BaseService.extend({
       redirect_uri: config.redirect_uri,
     };
     const url = `https://login.live.com/oauth20_authorize.srf?${dumpQuery(params)}`;
-    browser.tabs.create({ url });
+    openAuthPage(url, config.redirect_uri);
   },
   checkAuth(url) {
     const redirectUri = `${config.redirect_uri}?code=`;