Introduction
I was having an issue where Chrome was refusing to show an <iframe>
served on my Nginx web server and returning an error in console:
“Refused to display ‘URL’ in a frame because it set ‘X-Frame-Options’ to ‘deny'”
You will get this error if the Nginx config setting X-Frame-Options
is set to DENY
.
However, I couldn’t find that setting in any of the config files I checked, so I added X-Frame-Options: SAMEORIGIN
to my main Nginx config file and Chrome came up with another error.
Refused to display ‘URL’ in a frame because it set multiple ‘X-Frame-Options’ headers with conflicting values (‘DENY, SAME-ORIGIN’). Falling back to ‘deny’.
You can resolve this by searching your Nginx config files for the X-Frame-Options
setting and commenting them out.
Search Nginx Config for “X-Frame-Options”
Running this command will search for the X-Frame-Options
setting in the Nginx directory.
sudo grep -iRl "X-Frame-Options" /etc/nginx/
Output:
/etc/nginx/snippets/ssl-params.conf
In my case, I found this setting in the ssl-params.conf
file (sometimes called ssl-dhparams.conf
). For you, this setting might be found in a different Nginx config file.
To edit this file:
sudo nano /etc/nginx/snippets/ssl-params.conf
Output:
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# disable HSTS header for now
#add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload$
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
Above we can see the X-Frame-Options
is set to DENY
, which will prevent iframes from loading content in the browser.
You can either change this to SAMEORIGIN
or just comment out the line with a #
sign and Nginx will default to SAMEORIGIN
. Both methods should produce the same result.
add_header X-Frame-Options SAMEORIGIN;
– OR –
#add_header X-Frame-Options DENY;
Save and exit (press CTRL
+ X
, press Y
and then press ENTER
)
Test Nginx config.
sudo nginx -t
Output:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
If test succesful, restart Nginx.
sudo service nginx reload
Now you can try refreshing the page in your browser to see if the error goes away.
Understanding X-Frame-Options
The X-Frame-Options
HTTP response header can be used to indicate whether or not a browser should be allowed to render a page in a <frame>
, <iframe>
, <embed>
or <object>
. Sites can use this to avoid clickjacking attacks, by ensuring that their content is not embedded into other sites.
There are two possible directives for X-Frame-Options
:
X-Frame-Options: DENY
X-Frame-Options: SAMEORIGIN
If you specify DENY
, not only will attempts to load the page in a frame fail when loaded from other sites, attempts to do so will fail when loaded from the same site.
On the other hand, if you specify SAMEORIGIN
, you can still use the page in a frame as long as the site including it in a frame is the same as the one serving the page.
Let me know if this helped. Follow me on Twitter, Facebook and YouTube, or 🍊 buy me a smoothie.
Thaks alot man…really appriciate it…I was trying to solve this issue for the past 2 days. Thanks alot.
Thanks for the article. You’ve used SAME-ORIGIN and SAMEORIGIN in different examples. I believe it should be the latter.
Looking for this missing setting throughout nginx config files was driving me mad after getting the “conflicting values” error in chrome console. I quickly found the offending file using your method and it turned out to be a config snippet I wrote 12+ months ago [egg on face]. I take back all the profanities directed at Nginx xD