Skip to content
This repository has been archived by the owner on Jan 17, 2023. It is now read-only.

Fix #3600, warn about failed login due to third party cookies #3632

Merged
merged 1 commit into from
Dec 4, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion addon/webextension/sitehelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ this.sitehelper = (function() {
let shotId = event.detail;
catcher.watchPromise(callBackground("getAuthInfo", shotId || null).then((info) => {
sendBackupCookieRequest(info.authHeaders);
sendCustomEvent("login-successful", {deviceId: info.deviceId, isOwner: info.isOwner});
sendCustomEvent("login-successful", {deviceId: info.deviceId, isOwner: info.isOwner, backupCookieRequest: true});
}));
}));

Expand Down
2 changes: 2 additions & 0 deletions locales/en-US/server.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@ timeDiffFutureDays = { $number ->
*[other] in { $number } days
}

errorThirdPartyCookiesEnabled = If you took this shot and cannot delete it, you may need to temporarily enable third party cookies from your browser’s preferences.


[[ Shotindex page ]]

Expand Down
23 changes: 18 additions & 5 deletions server/src/pages/shot/view.js
Original file line number Diff line number Diff line change
Expand Up @@ -315,9 +315,9 @@ class Body extends React.Component {
}

let errorMessages = [
<Localized id="shotPageAlertErrorUpdatingExpirationTime" key="error-1"><div id="shotPageAlertErrorUpdatingExpirationTime" hidden></div></Localized>,
<Localized id="shotPageAlertErrorDeletingShot" key="error-2"><div id="shotPageAlertErrorDeletingShot" hidden></div></Localized>,
<Localized id="shotPageAlertErrorUpdatingTitle" key="error-3"><div id="shotPageAlertErrorUpdatingTitle" hidden></div></Localized>,
<Localized id="shotPageAlertErrorUpdatingExpirationTime" key="error-1"><div id="shotPageAlertErrorUpdatingExpirationTime" className="clips-warning" hidden></div></Localized>,
<Localized id="shotPageAlertErrorDeletingShot" key="error-2"><div id="shotPageAlertErrorDeletingShot" className="clips-warning" hidden></div></Localized>,
<Localized id="shotPageAlertErrorUpdatingTitle" key="error-3"><div id="shotPageAlertErrorUpdatingTitle" className="clips-warning" hidden></div></Localized>,
<Localized id="shotPageConfirmDelete" key="error-4"><div id="shotPageConfirmDelete" hidden></div></Localized>
];

Expand Down Expand Up @@ -418,8 +418,11 @@ class Body extends React.Component {
</Localized>
</div>
</div>
{ clips }
{ errorMessages }
<section className="clips">
{ this.props.isOwner && this.props.loginFailed ? <LoginFailedWarning /> : null }
{ errorMessages }
{ clips }
</section>
<Footer forUrl={ shot.viewUrl } {...this.props} />
</div>
</reactruntime.BodyTemplate>);
Expand Down Expand Up @@ -654,5 +657,15 @@ class EditableTitle extends React.Component {

}

class LoginFailedWarning extends React.Component {
render() {
return <Localized id="errorThirdPartyCookiesEnabled">
<div className="clips-warning">
If you took this shot and cannot delete it, you may need to temporarily enable third party cookies from your browser’s preferences!!
</div>
</Localized>;
}
}

exports.BodyFactory = React.createFactory(Body);
exports.HeadFactory = React.createFactory(Head);
9 changes: 9 additions & 0 deletions server/src/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -648,6 +648,15 @@ app.post("/api/set-login-cookie", function(req, res) {
});
});

/** This endpoint is used by the site to confirm if the cookie was set */
app.get("/api/check-login-cookie", function(req, res) {
if (req.deviceId) {
simpleResponse(res, "Login OK", 200);
} else {
simpleResponse(res, "No credentials available", 401);
}
});

app.put("/data/:id/:domain",
upload.fields([{name: "blob", maxCount: 1}, {name: "thumbnail", maxCount: 1}]),
function(req, res) {
Expand Down
20 changes: 20 additions & 0 deletions static/css/frame.scss
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,26 @@
font-size: 15px;
}

.clips {
@include flex-container(column, center, center);
position: relative;
flex: 1;
}

.clips-warning {
background: #ffe900;
padding: 5px;
border-bottom: 1px solid #d7b600;
border-top: 1px solid #d7b600;
position: absolute;
text-align: center;
top: 0;
width: 100%;
color: $black;
font-size: 12px;
}


.clip-container {
@include flex-container(row, center, center);
flex: 0 auto;
Expand Down
39 changes: 35 additions & 4 deletions static/js/wantsauth.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* globals Raven */
/** This allows for early communication with the add-on to ask for authentication information
Including this script on a page indicates that the page would like to be authenticated
(and that it isn't currently authenticated)
Expand Down Expand Up @@ -32,16 +33,46 @@ window.wantsauth = (function() {

// These events are used to communicate with sitehelper.js:
document.addEventListener("login-successful", (event) => {
let {deviceId, isOwner} = JSON.parse(event.detail);
let {deviceId, isOwner, backupCookieRequest} = JSON.parse(event.detail);
savedAuthData = {
deviceId,
isOwner
isOwner,
loginFailed: false
};
for (let callback of authDataCallbacks) {
callback(savedAuthData);
let promise = Promise.resolve(true);
if (!backupCookieRequest) {
// The client may not support login with third party cookies turned off.
// We will do a request to confirm authentication really worked.
promise = checkLogin();
}
promise.then((loginWorked) => {
if (!loginWorked) {
savedAuthData.loginFailed = true;
}
}, (e) => { // Exception branch
console.warn("Error checking login:", e);
savedAuthData.loginFailed = true;
if (typeof Raven !== "undefined") {
Raven.captureException(e);
}
}).then(() => {
for (let callback of authDataCallbacks) {
callback(savedAuthData);
}
}).catch((e) => {
if (typeof Raven !== "undefined") {
Raven.captureException(e);
}
});
});

function checkLogin() {
return fetch('/api/check-login-cookie', {credentials: "include"}).then((resp) => {
// The server only returns 200 if the user is logged in
return resp.ok;
});
}

document.addEventListener("addon-present", () => {
document.dispatchEvent(new CustomEvent("request-login", {detail: maybeShotId}));
});
Expand Down