element-hq / element-web

A glossy Matrix collaboration client for the web.
https://element.io
GNU Affero General Public License v3.0
11.23k stars 2k forks source link

Question: Could it be possible to change the domain name while keeping the users logged in #15069

Closed n-peugnet closed 3 years ago

n-peugnet commented 4 years ago

Description

I currently have an instance of Riot on my server on the subdomain riot.mydomain.com. Now that the name has changed I would like to change the subdomain to element.mydomain.com. But as the domain is different, the browser does not send the cookies, which forces every users to log in again, openning a new session that they have to validate. I am wondering if it would be possible to make element keep the connection across different domains. Maybe by looking for the cookies of the previous domain ?

Do you think that could be possible ?

t3chguy commented 4 years ago

It doesn't use cookies, it use localStorage which the browser doesn't allow different subdomain to access each others.

n-peugnet commented 4 years ago

Ok, makes sense. So we could imagine some kind of migration script based on this idea that could copy on the new localStorage the content of the old one ?

t3chguy commented 4 years ago

Sure but it could be vulnerable to attacks.

n-peugnet commented 4 years ago

Considering the example of the article with this content in the iframe:

const domains = [
  "https://www.domain1.com",
  "https://www.domain2.com"
]

window.addEventListener("message", messageHandler, false);

function messageHandler(event) {
  if (!domains.includes(event.origin))
    return; 

  const { action, key, value } = event.data
  if (action == 'save'){
    window.localStorage.setItem(key, JSON.stringify(value))
  } else if (action == 'get') {
    event.source.postMessage({
      action: 'returnData',
      key,
      JSON.parse(window.localStorage.getItem(key))
    }, '*')
  }
}

Do you mean because the origin property of the event could be changed by an attacker to match one of the authorized domains ?

Because from what I'm reading on MDN docs the postMessage API is meant to exactly do this (exchanging data between domains in a secure and controlled way). This is the browser that triggers this event in the iframe, so this property should be correct.

As we are already trusting the browser's localStorage implementation to be safe, why not also trust the postMessage's one to be safe as well ?

turt2live commented 4 years ago

We explored something like this during the rename ourselves for our own instances and ultimately decided on having the redirection dialog seen in the early rebranded versions (it's since been removed).

Generally it's recommended to keep both running for a bit and let the "Riot is now Element" dialog take care of this.

n-peugnet commented 4 years ago

As most of my instance's users are not experienced users, I want to make the domain transition completely seamless. I know from experience that the "Riot is now Element" dialog will not be sufficient. Moreover, the users who will just skip it are especially the ones that would have trouble to login again, which will ultimately make them stop using Matrix.

This is what I want to avoid.

At the same time, having a domain riot.mydomain.com pointing to an app called Element is disturbing for the users and can lead to incomprehension. I am talking about non-IT people who come from apps like Discord and who already have trouble understanding why there are multiple names for a discussion app. I think that Matrix has the potential to be simple enough for this kind of users but this is small details like this one that can ruin the entire effort IMO.

I could make this script for my own needs, only to migrate the users of my instance. What I need to know though is what are the data I need to transfer from the old domain to the new one. Currently, from my point of view, an iframe + postMessage seems to be secure enough for my use case, so I will try to use this solution. Except if you think there is a real security issue with it.

turt2live commented 4 years ago

Element stores data in indexeddb and localstorage, both of which need to be present before the app loads.

In general trying to bypass the origin restrictions put in place by browsers is not a good idea, particularly if someone else decides to put your Riot into an iframe of theirs and steal data from your users. There are ways to minimize this, though it's still not impossible when a postMessage API is exposed. It is never a good idea to expose credentials over postMessage if it can be avoided.

From personal experience, when dealing with highly non-technical users it is often better to just take the time to try and walk them through the name change than reduce their security. It will be painful, but at least your users will navigate the transition safely and might even learn a bit more about the platform you're offering.

afranke commented 3 years ago

Closing as the question has been answered and there doesn’t seem to be any issue left to resolve.