FEATURE: Allow embedding to ignore HTTP REFERER

New site setting: `embed_any_origin` that will send postMessages to
wildcard origins `*` instead of the referer.

Most of the time you won't want to do this, so the setting is default to
`false`. However, there are certain situations where you want to allow
embedding to send post messages when there is no HTTP REFERER.

For example, if you created a native mobile app and you wanted to embed a list
of Discourse topics as HTML. In the code your HTML would be a
static file/string, which would not be able to send a referer. In this
case, the site setting will allow the embed to work.

From a security standpoint we currently only use `postMessage` to send
data about the size of the HTML document and scroll position, so it
should be enable if required with minimal security ramifications.
This commit is contained in:
Robin Ward 2019-09-10 12:27:07 -04:00
parent cf23016360
commit 1cebe7670a
5 changed files with 27 additions and 5 deletions

View File

@ -8,7 +8,7 @@ class EmbedController < ApplicationController
skip_before_action :check_xhr, :preload_json, :verify_authenticity_token
before_action :ensure_embeddable, except: [ :info, :topics ]
before_action :get_embeddable_css_class, except: [ :info, :topics ]
before_action :prepare_embeddable, except: [ :info ]
before_action :ensure_api_request, only: [ :info ]
layout 'embed'
@ -123,10 +123,13 @@ class EmbedController < ApplicationController
private
def get_embeddable_css_class
def prepare_embeddable
@embeddable_css_class = ""
embeddable_host = EmbeddableHost.record_for_url(request.referer)
@embeddable_css_class = " class=\"#{embeddable_host.class_name}\"" if embeddable_host.present? && embeddable_host.class_name.present?
@data_referer = request.referer
@data_referer = '*' if SiteSetting.embed_any_origin? && @data_referer.blank?
end
def ensure_api_request

View File

@ -13,7 +13,7 @@
<title><%= @topic_view.page_title %> - <%= SiteSetting.title %></title>
<%- end %>
<meta id="data-embedded" data-referer="<%= request.referer %>">
<meta id="data-embedded" data-referer="<%= @data_referer %>">
<%= preload_script 'embed-application' %>
<%= yield :head %>

View File

@ -1959,6 +1959,7 @@ en:
autohighlight_all_code: "Force apply code highlighting to all preformatted code blocks even when they didn't explicitly specify the language."
highlighted_languages: "Included syntax highlighting rules. (Warning: including too many languages may impact performance) see: <a href='https://highlightjs.org/static/demo/' target='_blank'>https://highlightjs.org/static/demo</a> for a demo"
embed_any_origin: "Allow embeddable content regardless of origin. This is required for mobile apps with static HTML."
embed_topics_list: "Support HTML embedding of topics lists"
embed_truncate: "Truncate the embedded posts."
embed_support_markdown: "Support Markdown formatting for embedded posts."

View File

@ -859,6 +859,7 @@ posting:
choices:
- 4-spaces-indent
- code-fences
embed_any_origin: false
embed_topics_list: false
embed_truncate:
default: true

View File

@ -88,12 +88,29 @@ describe EmbedController do
it "returns a list of topics" do
topic = Fabricate(:topic)
get '/embed/topics?discourse_embed_id=de-1234', headers: headers
get '/embed/topics?discourse_embed_id=de-1234', headers: {
'REFERER' => 'https://example.com/evil-trout'
}
expect(response.status).to eq(200)
expect(response.headers['X-Frame-Options']).to eq("ALLOWALL")
expect(response.body).to match("data-embed-id=\"de-1234\"")
expect(response.body).to match("data-topic-id=\"#{topic.id}\"")
expect(response.body).to match("data-referer=\"https://example.com/evil-trout\"")
end
it "returns no referer if not supplied" do
get '/embed/topics?discourse_embed_id=de-1234'
expect(response.status).to eq(200)
expect(response.body).to match("data-referer=\"\"")
end
it "returns * for the referer if `embed_any_origin` is set" do
SiteSetting.embed_any_origin = true
get '/embed/topics?discourse_embed_id=de-1234'
expect(response.status).to eq(200)
expect(response.body).to match("data-referer=\"\\*\"")
end
end
end