Search code examples
springtomcatiframesubdomainx-frame-options

enable subdomain iframe access


I am trying to display iframe from x.example.com on a web page hosted at y.example.com

Here are the settings that I have done so for

Tomcat:

<filter>
    <filter-name>ClickJackFilterEnabled</filter-name>
    <filter-class>org.apache.catalina.filters.HttpHeaderSecurityFilter</filter-class>
    <init-param>
        <param-name>antiClickJackingEnabled</param-name>
        <param-value>false</param-value>
    </init-param>
</filter>

<filter-mapping>
    <filter-name>ClickJackFilterEnabled</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

Spring Security:

    httpResponse.setHeader("Content-Security-Policy", "default-src 'self' *.example.com; style-src 'self' *.googleapis.com *.amazonaws.com 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; child-src 'self' *.example.com; font-src *;img-src 'self' *.amazonaws.com");
    httpResponse.setHeader("Access-Control-Allow-Origin", "http://*.example.com");

When I open the page with embedded iframs, I am still getting this error:

Refused to display 'http://x.example.com/' in a frame because it set 'X-Frame-Options' to 'SAMEORIGIN'.

Uncaught SecurityError: Sandbox access violation: Blocked a frame at "http://y.example.com" from accessing a frame at "http://x.example.com".  The frame being accessed is sandboxed and lacks the "allow-same-origin" flag.

When I checked the headers using curl, the header X-Frame-Options does not exist

This the the output of curl

* Rebuilt URL to: y.example.com/
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
   0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0*   Trying 127.0.0.1...
* Connected to y.example.com (127.0.0.1) port 80 (#0)
> GET / HTTP/1.1
> Host: y.example.com
> User-Agent: curl/7.47.0
> Accept: */*
> 
< HTTP/1.1 200 OK
< Server: Apache-Coyote/1.1
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< X-Application-Context: application:dev:8080
< Content-Security-Policy: default-src 'self' *.example.com; style-src 'self' *.googleapis.com *.amazonaws.com 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; child-src 'self' *.example.com; font-src *;img-src 'self' *.amazonaws.com
< Access-Control-Allow-Origin: http://*.example.com
< Content-Type: text/html;charset=UTF-8
< Content-Language: en-IN
< Transfer-Encoding: chunked
< Date: Wed, 20 Jul 2016 13:21:57 GMT
< 
{ [8200 bytes data]

What am I missing?

UPDATE:

I tried to set

document.domain = "example.com"

On both the web pages, I am still getting the error

Refused to display 'http://x.example.com/' in a frame because it set 'X-Frame-Options' to 'SAMEORIGIN'

When I type

document.domain

in the javascript console, I am getting

"example.com"

On both the web pages. So the origin is same for both the pages.


Solution

  • Finally I was able solve the issue. The problem is probably with how browsers deal with X-Frame-Options header.

    The concept behind setting

    document.domain = "example.com" 
    

    is to make the origin same for both the web pages. Browsers allow setting origin to a parent domain, so a page at a.x.example.com can set value of document.domain to x.example.com or to example.com

    Now, even after setting document.domain to example.com, I was getting the error

    Refused to display 'http://x.example.com/' in a frame because it set 'X-Frame-Options' to 'SAMEORIGIN'
    

    When I removed the X-Frame-Options header altogether, using

    http.headers().frameOptions().disable();
    

    In securityConfiguration.java, it worked!

    I don't know the reason why browsers didn't honour the document.domain setting. Couldn't find anything on this in mozilla documentation, or anywhere else. Hope this helps someone.