Closed rhclayto closed 3 years ago
I'm not sure how active the development here is, but I wrote the Default container feature a while ago and somehow still get notifications :/ Anyway, thanks for the detailed report.
The default container should only trigger as a backup when a match hasn't been found
What I'm guessing is actually happening is that there are multiple redirects (probably 2) of which the first one is to a site not covered by your glob and then the second one is. To confirm this, could you please enable persistent logs in the network tab of the developer tools?
(How, just in case you don't know)
Then repeat your actions verify the 3xx requests.
Thanks for your response.
In a private window with all extensions disabled & with persistent logging enabled, I fill in the credentials & click the login button on www.somebank.com
. Here is what happens:
1) A POST request to https://secure.somebank.com/tob/live/usp-core/app/initialLogin
- status 200. That page is a loading page which makes GET requests to a loader GIF, & two javascript files, both status 200.
2) One of the javascripts initiates a POST request to https://secure.somebank.com/cdn-cgi/bm/cv/result
, & the POST payload looks like it is some kind of browser fingerprinting (it contains screen dimensions amongst other things) for the 'We don't recognize this device' stuff.
3) The other loaded javascript makes a POST request to https://secure.somebank.com/tob/live/usp-core/app/redirectInitialLogin
, which receives a 303 See Other
status from the server. The Location header in the 303 response points to /tob/live/usp-core/app/mfa
.
4) The GET request to the redirect page https://secure.somebank.com/tob/live/usp-core/app/mfa
is status 200. The page displayed is a 'we don't recognize this device, confirm identity with e-mail or text' page. By this point, when Containerise is enabled, the container has already switched to default No Container & the session is lost, i.e., this identity confirmation page is never actually displayed. The container then switches back to Banking & the page is redirected to the home page https://www.somebank.com
.
5) After confirming my identity via SMS, the confirmation page issues a POST request to https://secure.somebank.com/tob/live/usp-core/app/postLogin
, which receives a 303 status with Location header /tob/live/usp-core/app/home
, which successfully GETS the online banking dashboard page.
If I have previously confirmed my device & registered it, the login process goes directly from redirectInitialLogin
which issues a 303 redirect to postLogin
which also issues a 303 which redirects to the dashboard.
With Containerise enabled as described in my first post, it looks like at the first 303 it opens a new default tab beside the Banking containerized tab I am working in, then quickly deletes the original banking tab & containerizes the new tab into Banking. (This is very rapid but is visibly perceptible.) I lose the developer tools panel when this happens, so I can't see how the login flow works in this scenario. For certain though without Containerise, there are two 303 redirects, but they are both to secure.somebank.com
, which is matched by the glob rule. Also without Containerise & default tab option, it doesn't do the thing where it makes a new tab, deletes the first, then switches the new tab to the container. I believe this is where the breakage of login flow works (the login state is in the tab that gets deleted). I had a look at the code to see what might cause this behavior, but haven't been able to wrap my head around it yet.
Edit: Confirmation of my observation that Containerise opens the redirect in a new default tab, deletes the original tab, & switches the new tab to the Banking container, all in rapid succession. If I turn on the 'Keep old tabs' option, when I submit the login form, a new default 'No Container' tab is opened next to the original tab, then switched to a Banking container. The login form tab remains in place, & in the network tab of developer tools I see that the POST request to https://secure.somebank.com/tob/live/usp-core/app/initialLogin
has been denied, with the message under the Transferred field of 'Blocked by Containerise'. This is before any 303 response redirects. No more network requests after that. Whatever is causing this behavior is the source of the problem.
It looks like the code in containers.js is using the underlying Firefox browser.tabs.create()
API method:
Could this be causing this behavior? And I see there is a browser.tabs.update
method as well: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/update Would this perhaps allow updating the location in the same tab, rather than the 'create new tab, delete old tab, containerize new tab' dance?
New comment to lessen wall of text effect.
I built the xpi from source with some console.log lines thrown in. I noticed that when clicking the login button, which sends the POST request from step 1 in the previous comment, the hostIdentity
variable is undefined, which causes Containerise to think it's going to an unmatched URL, so it tries to do it in a default container. It's getting hostIdentity
undefined because the hostMap
variable is an empty object for the request in question. Normal navigation, such as from https://www.somebank.com
to https://www.somebank.com/login
, does populate the hostMap
object. hostMap
is set here:
(P.S.: I have tried it with 'Match domain only' preference set & unset, same result either way.)
Here is the whole console log for a single attempt (i.e., click the login button, new default tab opens, old tab closes, new default tab is containerized into the container the old tab was in). The log titles are the same as the variables being logged.
url: https://secure.somebank.com/tob/live/usp-core/app/initialLogin index.js:1:11386
tabId: 16 index.js:1:11409
creatingTabs:
Object { }
index.js:1:11450
creatingUrl: undefined index.js:1:11482
hostMap:
Object { }
index.js:1:11688
identities:
(5) […]
?
0: Object { name: "Personal", icon: "fingerprint", iconUrl: "resource://usercontext-content/fingerprint.svg", … }
?
1: Object { name: "Work", icon: "briefcase", iconUrl: "resource://usercontext-content/briefcase.svg", … }
?
2: Object { name: "Banking", icon: "dollar", iconUrl: "resource://usercontext-content/dollar.svg", … }
?
3: Object { name: "Shopping", icon: "cart", iconUrl: "resource://usercontext-content/cart.svg", … }
?
4: Object { name: "No Container", icon: "circle", iconUrl: "resource://usercontext-content/circle.svg", … }
?
length: 5
?
<prototype>: Array []
index.js:1:11715
currentTab:
{…}
?
active: true
?
attention: false
?
audible: false
?
cookieStoreId: "firefox-container-3"
?
discarded: false
?
favIconUrl: "data:image/x-icon;base64,<redacted>"
?
height: 1095
?
hidden: false
?
highlighted: true
?
id: 16
?
incognito: false
?
index: 3
?
isArticle: false
?
isInReaderMode: false
?
lastAccessed: 1612058898604
?
mutedInfo: Object { muted: false }
?
pinned: false
?
sharingState: Object { camera: false, microphone: false, screen: undefined }
?
status: "loading"
?
successorTabId: -1
?
title: "Some Bank Login"
?
url: "https://www.somebank.com/login"
?
width: 958
?
windowId: 1
?
<prototype>: Object { … }
index.js:1:11745
hostIdentity: undefined index.js:1:11862
Going to open https://secure.somebank.com/tob/live/usp-core/app/initialLogin in default container firefox-default No Container index.js:1:12071
url: https://secure.somebank.com/tob/live/usp-core/app/initialLogin index.js:1:10798
newTabIndex: 4 index.js:1:10821
currentTabId: 16 index.js:1:10852
openerTabId: undefined index.js:1:10884
cookieStoreId: firefox-default index.js:1:10915
currentTab:
Object { id: 16, index: 3, windowId: 1, highlighted: true, active: true, attention: false, pinned: false, status: "loading", hidden: false, discarded: false, … }
index.js:1:10974
url: https://secure.somebank.com/tob/live/usp-core/app/initialLogin index.js:1:11386
tabId: 17 index.js:1:11409
creatingTabs:
Object { 17: "https://secure.somebank.com/tob/live/usp-core/app/initialLogin" }
index.js:1:11450
creatingUrl: https://secure.somebank.com/tob/live/usp-core/app/initialLogin index.js:1:11482
url: https://www.somebank.com/ index.js:1:11386
tabId: 17 index.js:1:11409
creatingTabs:
Object { 17: "https://secure.somebank.com/tob/live/usp-core/app/initialLogin" }
index.js:1:11450
creatingUrl: https://secure.somebank.com/tob/live/usp-core/app/initialLogin index.js:1:11482
hostMap:
Object { host: "!*.somebank.com", containerName: "Banking", cookieStoreId: "firefox-container-3", enabled: true }
index.js:1:11688
identities:
Array(5) [ {…}, {…}, {…}, {…}, {…} ]
index.js:1:11715
currentTab:
Object { id: 17, index: 3, windowId: 1, highlighted: true, active: true, attention: false, pinned: false, status: "loading", hidden: false, discarded: false, … }
index.js:1:11745
hostIdentity:
Object { name: "Banking", icon: "dollar", iconUrl: "resource://usercontext-content/dollar.svg", color: "green", colorCode: "#51cd00", cookieStoreId: "firefox-container-3" }
index.js:1:11862
url: https://www.somebank.com/ index.js:1:10798
newTabIndex: 4 index.js:1:10821
currentTabId: 17 index.js:1:10852
openerTabId: undefined index.js:1:10884
cookieStoreId: firefox-container-3 index.js:1:10915
currentTab:
Object { id: 17, index: 3, windowId: 1, highlighted: true, active: true, attention: false, pinned: false, status: "loading", hidden: false, discarded: false, … }
index.js:1:10974
url: https://www.somebank.com/ index.js:1:11386
tabId: 18 index.js:1:11409
creatingTabs:
Object { 18: "https://www.somebank.com/" }
index.js:1:11450
creatingUrl: https://www.somebank.com/ index.js:1:11482
url: https://www.somebank.com/ index.js:1:11386
tabId: 18 index.js:1:11409
creatingTabs:
Object { 18: "https://www.somebank.com/" }
index.js:1:11450
creatingUrl: https://www.somebank.com/
Okay, progress.
I found the code that is causing this, & a change that remedies it. However, I'm not sure if there would be side effects from making the change.
The code is at:
And the change is:
get(url, matchDomainOnly) {
return super.getAll().then(maps => {
const sorted = sortMaps(Object.keys(maps).map(key => maps[key]));
// Sorts by domain length, then by path length
return sorted.find((map) => {
try{
return matchesSavedMap( url, matchDomainOnly, map);
} catch (e) {
console.error('Error matching maps', map, url, matchDomainOnly, e);
return false;
}
});
});
}
The return with OR statement was returning the fallback empty object. Removing the || {}
makes this work. Will this have side effects?
I will investigate further to see why that's happening to begin with under these circumstances.
Okie dokie! After all that, I found the solution, & it was simply that the bank website was redirecting from https://www.somebank**bank**.com
to https://secure.somebank.com
. I simply overlooked that they indeed switched the domain name. Bangs head against wall.
I have the following Containerise rule which containerizes a bank web site into the Banking container:
!*.somebank.com , Banking
I also have the Default Container option turned on, with the Container name set as 'No Container'.
The login form is at
https://www.somebank.com
. After submitting credentials, the web site uses a303 Redirect
HTTP response to redirect tohttps://secure.somebank.com
.What happens is that Containerize opens the
https://secure.somebank.com
that was redirected to in the same tab but in the default 'No Container', then quickly addshttps://secure.somebank.com
into the Banking container. This brief loss of the Banking container from before the redirect loses the session, the log in is unsuccessful.In short, a 303 Redirect inside a Containerised container with Default Container of 'No Container' doesn't keep both pages inside the same container, even though both are matched by the glob rule, but instead opens the redirect in the 'No Container' default & then switches back to the rule-matched container. This kills sessions.
The log in with redirect works inside the Banking container with:
1) Containerise disabled 2) The Default container option turned off 3) The Default container option turned on, but the Default Container name set to Banking.
The desired behavior would be to treat redirected-to sites that match the same glob rule as the site redirected-from, as internal navigation, not as a redirection to another site, triggering the default container, then rematching the rule & being put back into the original container.