decent-chat / decent

Open source messaging platform for the modern web
https://meta.decent.chat
GNU General Public License v3.0
21 stars 5 forks source link

Make Decent embeddable? #287

Open towerofnix opened 6 years ago

towerofnix commented 6 years ago

I'm curious about thoughts on this. It would be nice to be able to incorporate a Decent chat into, say, a live stream page. But I don't want to cause any security issues, either. If we use iframes (and ideally we would, since they're so portable), is there a way to configure header options to only be embeddable on the same domain? That way we avoid clickjacking, etc. (Ping @joker314.)

In terms of actual design, that could be handled by making the client responsive to sizes. Most live stream viewing sites put chat in a thin, tall column beside the video; obviously sidebars and such wouldn't fit there. See #240 (actually there's not much discussion there yet, haha).

bates64 commented 6 years ago

is there a way to configure header options to only be embeddable on the same domain

yes

joker314 commented 6 years ago

Yes, this is perfectly doable in a secure way. What you need to do is ensure that you can't perform state-changing actions on the embeddable page.

So, in the URL, mark whether a page is going to be embedded through /embed. If it is, then sending messages is disallowed as well as any other actions. This way, Clickjacking doesn't work because Clicking does nothing. The page is read-only. Then, for these /embed pages, we do X-Frame-Options: ALLOW and it works nicely. I like the idea, Flo 👍

joker314 commented 6 years ago

It's also quite easy to make a site read-only,

<div class="readonly">

</div>

<style>
.readonly {
  z-index: 100000;
  opacity: 0;
  position: fixed;
  height: 100%;
  width: 100%;
  padding: 0;
  margin: 0;
}
</style>

You're placing a transparent element on top of everything, so all clicks are sent over to the div and not the sensitive buttons. This makes it very easy to implement (just check for /embed and add a snippet code similar to the one above). However, it doesn't look like it's an embed, so a user may be confused if they try to send a message but it's not working.

We, therefore, need a way to indicate that a user is in embed mode. This could be done by having the div turn red when the mouse is down. Hopefully there's a CSS selector for that? In any case, we don't want it to just turn red, we also want it to describe what's going on ("Sorry, but you're in read-only mode. This is designed for embedding pages. If you want to use all the features of our Decent client, go here ").

Or we could use *gasps* JavaScript since the rest of the site relies on it (WebSockets, etc.)

bates64 commented 6 years ago

Does clickjacking allow a 'jacker' to run arbitrary JS on the target (/embed) page? Asking because we rely on localStorage currently to store the user's sessionID.

joker314 commented 6 years ago

Nope, Clickjacking is simply about channeling user interactions to the victim webpage rather than the attacker's. It does not affect JavaScript 🙂

joker314 commented 6 years ago

Okay, how about we have our /embed endpoint do

if(window.top === window.self) {
  alert("You're in a read-only view.")
}

This will not fire in a frame, but will fire as a top page. People shouldn't ever be trying to visit /embed as a top page, so we should give them a link to the normal version that allows user interaction.

bates64 commented 6 years ago

Could we just make /embed redirect?

joker314 commented 6 years ago

Totally, but developers who want to test the link out might get a little confuzzled.

bates64 commented 6 years ago

I'd say display a modal, then.

towerofnix commented 6 years ago

So, in the URL, mark whether a page is going to be embedded through /embed. If it is, then sending messages is disallowed as well as any other actions. This way, Clickjacking doesn't work because Clicking does nothing. The page is read-only.

@joker314 I guess I'm missing something here? Because the point is to have an embeddable, interactive chat. Put a live stream chat beside the video element, and let people type into it.

OTOH I think you're talking about being able to embed the app on sites which are not necessarily the same as the client host (e.g. hosting meta.decent.chat/embed on example.github.io)? Because clickjacking can only be an issue when you don't know what an embedding page might do, right? If you're embedding your client on your own site, then you know exactly what code is going to run, so you don't need to worry about clickjacking.

joker314 commented 6 years ago

Yep, okay, so new plan:

bates64 commented 6 years ago

I think that we could add an Embed/widget page under server settings that gives you the <iframe> code and a 'valid embed hosts' setting that affects X-Frame-Options.