Bug 1705745 - Remove authentication code from screenshots r=sfoster

Differential Revision: https://phabricator.services.mozilla.com/D141918
This commit is contained in:
Joaquín Serna 2022-03-28 21:28:07 +00:00
Родитель dfd75c103a
Коммит cf4d1e50b4
8 изменённых файлов: 3 добавлений и 4404 удалений

Просмотреть файл

@ -1,209 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
/* globals log */
/* globals main, deviceInfo, catcher, communication, browser */
"use strict";
this.auth = (function() {
const exports = {};
let registrationInfo;
let initialized = false;
let authHeader = null;
let sentryPublicDSN = null;
let abTests = {};
let accountId = null;
const fetchStoredInfo = catcher.watchPromise(
browser.storage.local.get(["registrationInfo", "abTests"]).then(result => {
if (result.abTests) {
abTests = result.abTests;
}
if (result.registrationInfo) {
registrationInfo = result.registrationInfo;
}
})
);
function generateRegistrationInfo() {
const info = {
secret: crypto.randomUUID(),
registered: false,
};
return info;
}
function register() {
return new Promise((resolve, reject) => {
const registerUrl = main.getBackend() + "/api/register";
// TODO: replace xhr with Fetch #2261
const req = new XMLHttpRequest();
req.open("POST", registerUrl);
req.setRequestHeader("content-type", "application/json");
req.onload = catcher.watchFunction(() => {
if (req.status === 200) {
log.info("Registered login");
initialized = true;
saveAuthInfo(JSON.parse(req.responseText));
resolve(true);
} else {
log.warn("Error in response:", req.responseText);
const exc = new Error("Bad response: " + req.status);
exc.popupMessage = "LOGIN_ERROR";
reject(exc);
}
});
req.onerror = catcher.watchFunction(() => {
const exc = new Error("Error contacting server");
exc.popupMessage = "LOGIN_CONNECTION_ERROR";
reject(exc);
});
req.send(
JSON.stringify({
secret: registrationInfo.secret,
deviceInfo: JSON.stringify(deviceInfo()),
})
);
});
}
function login(options) {
const { ownershipCheck, noRegister } = options || {};
return new Promise((resolve, reject) => {
return fetchStoredInfo.then(() => {
if (!registrationInfo) {
registrationInfo = generateRegistrationInfo();
log.info("Generating new device authentication ID", registrationInfo);
browser.storage.local.set({ registrationInfo });
}
const loginUrl = main.getBackend() + "/api/login";
// TODO: replace xhr with Fetch #2261
const req = new XMLHttpRequest();
req.open("POST", loginUrl);
req.onload = catcher.watchFunction(() => {
if (req.status === 404) {
if (noRegister) {
resolve(false);
} else {
resolve(register());
}
} else if (req.status >= 300) {
log.warn("Error in response:", req.responseText);
const exc = new Error("Could not log in: " + req.status);
exc.popupMessage = "LOGIN_ERROR";
reject(exc);
} else if (req.status === 0) {
const error = new Error("Could not log in, server unavailable");
error.popupMessage = "LOGIN_CONNECTION_ERROR";
reject(error);
} else {
initialized = true;
const jsonResponse = JSON.parse(req.responseText);
log.info("Screenshots logged in");
saveAuthInfo(jsonResponse);
if (ownershipCheck) {
resolve({ isOwner: jsonResponse.isOwner });
} else {
resolve(true);
}
}
});
req.onerror = catcher.watchFunction(() => {
const exc = new Error("Connection failed");
exc.url = loginUrl;
exc.popupMessage = "CONNECTION_ERROR";
reject(exc);
});
req.setRequestHeader("content-type", "application/json");
req.send(
JSON.stringify({
secret: registrationInfo.secret,
deviceInfo: JSON.stringify(deviceInfo()),
ownershipCheck,
})
);
});
});
}
function saveAuthInfo(responseJson) {
accountId = responseJson.accountId;
if (responseJson.sentryPublicDSN) {
sentryPublicDSN = responseJson.sentryPublicDSN;
}
if (responseJson.authHeader) {
authHeader = responseJson.authHeader;
if (!registrationInfo.registered) {
registrationInfo.registered = true;
catcher.watchPromise(browser.storage.local.set({ registrationInfo }));
}
}
if (responseJson.abTests) {
abTests = responseJson.abTests;
catcher.watchPromise(browser.storage.local.set({ abTests }));
}
}
exports.maybeLogin = function() {
if (!registrationInfo) {
return Promise.resolve();
}
return exports.authHeaders();
};
exports.authHeaders = function() {
let initPromise = Promise.resolve();
if (!initialized) {
initPromise = login();
}
return initPromise.then(() => {
if (authHeader) {
return { "x-screenshots-auth": authHeader };
}
log.warn("No auth header available");
return {};
});
};
exports.getSentryPublicDSN = function() {
return sentryPublicDSN;
};
exports.getAbTests = function() {
return abTests;
};
exports.isRegistered = function() {
return registrationInfo && registrationInfo.registered;
};
communication.register("getAuthInfo", (sender, ownershipCheck) => {
return fetchStoredInfo.then(() => {
// If a device id was never generated, report back accordingly.
if (!registrationInfo) {
return null;
}
return exports.authHeaders().then(authHeaders => {
let info = registrationInfo;
if (info.registered) {
return login({ ownershipCheck }).then(result => {
return {
isOwner: result && result.isOwner,
accountId,
authHeaders,
};
});
}
info = Object.assign({ authHeaders }, info);
return info;
});
});
});
return exports;
})();

Просмотреть файл

@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file, * License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */ * You can obtain one at http://mozilla.org/MPL/2.0/. */
/* globals browser, getStrings, selectorLoader, analytics, communication, catcher, log, auth, senderror, startBackground, blobConverters, startSelectionWithOnboarding */ /* globals browser, getStrings, selectorLoader, analytics, communication, catcher, log, senderror, startBackground, blobConverters, startSelectionWithOnboarding */
"use strict"; "use strict";

Просмотреть файл

@ -2,15 +2,13 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file, * License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */ * You can obtain one at http://mozilla.org/MPL/2.0/. */
/* globals startBackground, analytics, communication, Raven, catcher, auth, log, browser, getStrings */ /* globals startBackground, analytics, communication, catcher, log, browser, getStrings */
"use strict"; "use strict";
this.senderror = (function() { this.senderror = (function() {
const exports = {}; const exports = {};
const manifest = browser.runtime.getManifest();
// Do not show an error more than every ERROR_TIME_LIMIT milliseconds: // Do not show an error more than every ERROR_TIME_LIMIT milliseconds:
const ERROR_TIME_LIMIT = 3000; const ERROR_TIME_LIMIT = 3000;
@ -101,13 +99,6 @@ this.senderror = (function() {
log.error("Telemetry disabled. Not sending critical error:", e); log.error("Telemetry disabled. Not sending critical error:", e);
return; return;
} }
const dsn = auth.getSentryPublicDSN();
if (!dsn) {
return;
}
if (!Raven.isSetup()) {
Raven.config(dsn, { allowSecretKey: true }).install();
}
const exception = new Error(e.message); const exception = new Error(e.message);
exception.stack = e.multilineStack || e.stack || undefined; exception.stack = e.multilineStack || e.stack || undefined;
@ -138,13 +129,6 @@ this.senderror = (function() {
} }
} }
rest.stack = exception.stack; rest.stack = exception.stack;
Raven.captureException(exception, {
logger: "addon",
tags: { category: e.popupMessage },
release: manifest.version,
message: exception.message,
extra: rest,
});
}; };
catcher.registerHandler(errorObj => { catcher.registerHandler(errorObj => {

Просмотреть файл

@ -51,9 +51,7 @@ this.startBackground = (function() {
"blobConverters.js", "blobConverters.js",
"background/selectorLoader.js", "background/selectorLoader.js",
"background/communication.js", "background/communication.js",
"background/auth.js",
"background/senderror.js", "background/senderror.js",
"build/raven.js",
"build/shot.js", "build/shot.js",
"build/thumbnailGenerator.js", "build/thumbnailGenerator.js",
"background/analytics.js", "background/analytics.js",

Просмотреть файл

@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file, * License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */ * You can obtain one at http://mozilla.org/MPL/2.0/. */
/* globals browser, communication, getZoomFactor, shot, main, auth, catcher, analytics, blobConverters, thumbnailGenerator */ /* globals browser, communication, getZoomFactor, shot, main, catcher, analytics, blobConverters, thumbnailGenerator */
"use strict"; "use strict";

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -26,7 +26,6 @@ FINAL_TARGET_FILES.features["screenshots@mozilla.org"] += [
FINAL_TARGET_FILES.features["screenshots@mozilla.org"]["background"] += [ FINAL_TARGET_FILES.features["screenshots@mozilla.org"]["background"] += [
"background/analytics.js", "background/analytics.js",
"background/auth.js",
"background/communication.js", "background/communication.js",
"background/deviceInfo.js", "background/deviceInfo.js",
"background/main.js", "background/main.js",
@ -38,7 +37,6 @@ FINAL_TARGET_FILES.features["screenshots@mozilla.org"]["background"] += [
FINAL_TARGET_FILES.features["screenshots@mozilla.org"]["build"] += [ FINAL_TARGET_FILES.features["screenshots@mozilla.org"]["build"] += [
"build/inlineSelectionCss.js", "build/inlineSelectionCss.js",
"build/raven.js",
"build/selection.js", "build/selection.js",
"build/shot.js", "build/shot.js",
"build/thumbnailGenerator.js", "build/thumbnailGenerator.js",

Просмотреть файл

@ -9,10 +9,6 @@
"use strict"; "use strict";
this.sitehelper = (function() { this.sitehelper = (function() {
// This gives us the content's copy of XMLHttpRequest, instead of the wrapped
// copy that this content script gets:
const ContentXMLHttpRequest = content.XMLHttpRequest;
catcher.registerHandler(errorObj => { catcher.registerHandler(errorObj => {
callBackground("reportError", errorObj); callBackground("reportError", errorObj);
}); });
@ -32,40 +28,6 @@ this.sitehelper = (function() {
document.dispatchEvent(new CustomEvent(name, { detail })); document.dispatchEvent(new CustomEvent(name, { detail }));
} }
/** Set the cookie, even if third-party cookies are disabled in this browser
(when they are disabled, login from the background page won't set cookies) */
function sendBackupCookieRequest(authHeaders) {
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1295660
// This bug would allow us to access window.content.XMLHttpRequest, and get
// a safer (not overridable by content) version of the object.
// This is a very minimal attempt to verify that the XMLHttpRequest object we got
// is legitimate. It is not a good test.
if (
Object.toString.apply(ContentXMLHttpRequest) !==
"function XMLHttpRequest() {\n [native code]\n}"
) {
console.warn("Insecure copy of XMLHttpRequest");
return;
}
const req = new ContentXMLHttpRequest();
req.open("POST", "/api/set-login-cookie");
for (const name in authHeaders) {
req.setRequestHeader(name, authHeaders[name]);
}
req.send("");
req.onload = () => {
if (req.status !== 200) {
console.warn(
"Attempt to set Screenshots cookie via /api/set-login-cookie failed:",
req.status,
req.statusText,
req.responseText
);
}
};
}
registerListener( registerListener(
"delete-everything", "delete-everything",
catcher.watchFunction(event => { catcher.watchFunction(event => {
@ -73,25 +35,6 @@ this.sitehelper = (function() {
}, false) }, false)
); );
registerListener(
"request-login",
catcher.watchFunction(event => {
const shotId = event.detail;
catcher.watchPromise(
callBackground("getAuthInfo", shotId || null).then(info => {
if (info) {
sendBackupCookieRequest(info.authHeaders);
sendCustomEvent("login-successful", {
accountId: info.accountId,
isOwner: info.isOwner,
backupCookieRequest: true,
});
}
})
);
})
);
registerListener( registerListener(
"copy-to-clipboard", "copy-to-clipboard",
catcher.watchFunction(event => { catcher.watchFunction(event => {