- ๐บ๐ธUnited States sidgrafix
I have a working solution for anyone still looking.
Requirements:
- Website hosted on Apache 2.4+ platform with access to Drupals core .htaccess file.
- Domain CNAME DNS record for a Subdomain pointing to your main domain
- The 'Content-Security-Policy' (CSP) โ module installed
- (optional) The REMOTE_ADDR [IP Address] found under Apache Environment listed on php-info (admin/reports/status/php) page. I'm not sure if it will be available for anyone on a shared hosting platform without a dedicated IP address. Also if it matches your IP don't use it (I read somewhere the REMOTE_ADDR is the users IP when not set/specified) and if that is the case it won't work in a live hosting environment. For my use case the REMOTE_ADDR is static and was the option I chose for the allowed access.Note: in the following example the subdomain is 'media' using 'example.com' as the domain - change those to match your subdomain and domain.
Assuming you have a correctly set up CNAME DNS record specifically for use as the alternate domain used for the oEmbed media option setting.
If you were just starting to set things up - by default without any modifications this would mean anyone visiting "media.example.com" would see and have access to the same Drupal site at "example.com". Bad for two reasons SEO and user confusion, but we will fix that.
- That said, if you create content at this point on "example.com" and add a linked video from say youtube via a media field, you would likely run into cross site load error where the iframe should display when viewing the published content and is were the CSP module helps.
- If your at this point activate the (CSP) Content-Security-Policy module and at a minimum you'll have to configure in "Enforced" Policies "Directives" "frame-ancestors" by checking it on, setting the sub option "Self" and then adding your subdomain to the "Additional Sources" https://media.example.com
- Odds are "when using this module" especially if this is a live site you'll also have to set additional policies because by default it acts as security measure and denies other scripts and resources your site will try to load for example google maps and other 3rd party scripts and css. This can be a little complicated but easiest way to get through it is to use your browsers console which will output each denial with a tag that will match in CSP modules "Enforced" "Directives" like 'object-src and script-src', I found anything related to the oEmbed media coming from the subdomain by ticking on "self" and adding the subdomain to additional sources as well as enabling whatever identifier the browser console displayed for that "Directive" like 'unsafe-inline or unsafe-hashes' got everything working, for some of the others (3rd party sources also loading on the page) you may need to play with the settings a little to you get everything working without any errors or notices. I also disabled "Report Only" polies options by unchecking "Enable 'Report Only'".
There is probably an even easier way aside from the use of the SCP module, I'm just not sure what that would be without modifying headers and responses.
If your past all that and media oembed iframes are now loading from the subdomain on your main domain your almost done.
Now to either deny access to the subdomain or redirect everything to your main domain "that is not needed for oEmbed media to display."
- please note simply redirecting all subdomain requests to the main domain will not work (doing that would negate the use of an alternate domain to serve oEmbed content from and you would again see the warning about service oEmbed from the same site is not recommended.Add the following to your .htaccess as the last entry inside the so it runs last after any other rewrites or conditions you may be using like https enforcement, strip www or any other custom redirects runs first. Remember to change subdomain and domain names, plus "if" you are using a dedicated IP listed as REMOTE_ADDR (noted above) swap those as well.
# Check if HTTP_HOST is subdomain used for Media oEmbed. <If "%{HTTP_HOST} = 'media.example.com'> # Set the order for access. Order deny,allow # Start with deny all access. Deny from all # If HTTP_REFERER is main domain allow access (the last '/' after referer domain is needed). <If "%{HTTP_REFERER} == 'https://example\.com/'"> # If you have IP from REMOTE_ADDR replace 123.123.123.123 with the [REMOTE_ADDR] IP address if not remove or comment out 'Allow from 123.123.123.123'. # If on shared hosting platform without dedicated IP uncomment Allow from all and remove or comment out 'Allow from 123.123.123.123'. Allow from 123.123.123.123 # Allow from all </If> # If oEmbed is requesting resources from core media module let it. <ElseIf "%{REQUEST_URI} =~ m#/core/modules/media/#"> Allow from 123.123.123.123 # Allow from all </ElseIf> <Else> # If you do not want to redirect but instead deny access to any other part of the subdomain, empty or comment out everything in the 'Else' directive. Allow from 123.123.123.123 # Allow from all RewriteCond %{HTTP_HOST} ^media\.example\.com [NC] RewriteRule ^(.*) https://example.com%{REQUEST_URI} [L,R=301] </Else> </If>
I am by no means an expert on drupal, apache or htaccess, so it took some time getting things working (more like days of trial and error).
I found you couldn't just set allow all to IP if the HTTP_HOST was the subdomain (everything would still be user accessible at the subdomain), and it had to be the REMOTE_ADDR IP not the dedicated IP listed as SERVER_ADDR for it to work at all with IP.Using browser tools and seeing exactly what calls were made to the subdomain when displaying oEmbed media is how I finally worked it all out. First I found there were 2 resources needed, the oembed linked iframe and a css file from the core media module.
The oEmbed iframe link is passed by HTTP_REFERER of the main domain the css file is passed by HTTP_REFERER of the subdomain (but so is anything and everything if your viewing the site as the subdomain) and why I used a pattern match on the directive, should some things change and more files or other resources in the media module is needed for oEmbed in the future it should continue to work.
The (If, ElseIf and Else) Directives are only available to apache 2.4+
- Note the first thing I do in the opening if directive is set the access order as well as Deny access to all, in the following if, elseif and else you set the 'Allow for' so it will process. If you empty the last else or comment everything else it falls back to Deny for all and will show users landing on subdomain Forbidden, permission denied.Using either method 'Allow for [IP.ADDRESS]' or 'Allow for all' seams to work great, I tested both!
And as near I can tell this satisfies/mitigates any SEO (duplicate content), user confusion and Drupal's policy for oEmbed media!
Hopefully this will help others...
- ๐บ๐ธUnited States duntuk
@sidgrafix Holy shit... Thanks for this complex writeup.
I'm kind of puzzled at the lack of an official drupal explanation on how to accomplish this, especially since Drupal status page point this warning out on all the latest Drupal release versions.
Media
It is potentially insecure to display oEmbed content in a frame that is served from the same domain as your main Drupal site, as this may allow execution of third-party code. You can specify a different domain for serving oEmbed content here. - ๐บ๐ธUnited States liza
am flabbergasted at how badly this is being handled.
- ๐ฎ๐ณIndia newswatch Delhi/Bangalore
I put the iFrame domain as https://media.mydomain.com
This subdomain was created through Cpanel, with https://media.mydomain.com redirecting to https://mydomain.com
But I'm getting an error:
The requested URL was not found on this server.
Additionally, a 404 Not Found error was encountered while trying to use an ErrorDocument to handle the request.
It is astounding that something as basic as this does not have any documentation, and has been hanging fire for years now.
The text on /admin/config/media/media-settings is cryptic and confusing.
- ๐บ๐ธUnited States sidgrafix
@ newswatch - "You can't just create a subdomain and redirect it" it must be a CNAME record (or ALIAS record which is not supported by all DNS hosts, can't say for sure if cPanel does or not - it's been years since I've worked with a cPanel account) NOT an A record for a subdomain. This way (if CNAME) you'll have a canonical name (that the DNS name is an "alias" for) which points to your main domain.
- I know it's a bit much to work through (as I was once in your boat) but if you follow through with what I posted above https://www.drupal.org/project/drupal/issues/2965979#comment-14991459 โจ [PP-1] Validate alternate domain for oEmbed iFrame Postponed - in comment 75 - you should be able to get things set up and working. I 100% agree with you on this...
It is astounding that something as basic as this does not have any documentation, and has been hanging fire for years now.
The text on /admin/config/media/media-settings is cryptic and confusing.
If you have any questions or run into problems follow up here or send me a pm and I'll help anyway I can.. Best of luck!
- ๐ฎ๐ณIndia newswatch Delhi/Bangalore
Hi Michael: I changed my procedure a bit.
I did create a media.mydomian.com subdomain, but did not change doc root to public_html (like last time) and instead let it remain the default /home/username/media.mydomain.com
As of now the error/warning message has disappeared.
But whether this works or not I will know once I started using the module heavily across the site.
It's a fledgling site and still being built; so, I will need to keep a watch till I run into errors :)
- ๐ฌ๐งUnited Kingdom 2dareis2do
With regard my previous comment, I am switching this back on now as I figured out there was a misconfiguration of my ssl certificate.
- ๐บ๐ธUnited States marteenzh
I don't suppose there are any nginx experts out there who can provide an nginx version of the .htaccess code sidgrafix provided in 75 โจ [PP-1] Validate alternate domain for oEmbed iFrame Postponed ?
- ๐ฌ๐งUnited Kingdom matt b
I'm not embedding media from my own domain in an iframe. So... I don't need to worry about this right?
The annoying thing is I get the warning anyway and the only way to disable it is to put something in the field.
- ๐ฌ๐งUnited Kingdom scott_euser
There will be hosts that nginx/htaccess control is not granted in which case an event subscriber could throw an access denied if:
- Domain matches configured iframe domain
- Route is not media.oembed_iframe
Not sure whether that should be created as an issue in Core or if that's unlikely to get in and better as contrib? Any opinions?
Hard to do test coverage for it... Maybe need to briefly fudge it to pretend site URL is the iframe domain, test access denied thrown on everything except oembed route...