How to Set X-Frame-Options in Nginx, Apache, Flask and NodeJS

Published August 26, 2024

The X-Frame-Options header is used to prevent click-jacking attacks. Setting this header makes the browser to recognize whether a page can be rendered using of these tags <frame>, <iframe>, <embed> and <object>.

How to set X-Frame-Options in Nginx, Apache and Flask

What Is Clickjacking and How Does It Work?

In clickjacking, a malicious webpage tricks a user into clicking an element which is invisible or disguised as another element. Users can download malware, trojans or accidentally enter their credentials or make online purchases because they think this is a legitimate website.

A scammer can create a webpage that promises something great, maybe an expensive freebie or a vacation. Upon visiting the webpage, in the background, the malicious code will check if the user is logged into their bank or credit card website. If they are logged in, the browser navigates to the payment page of that bank or credit card website. This is done inside an invisible iframe above the freebie page with the payment button aligned over the freebie button. When the victim clicks on the freebie button, in reality, they have actually clicked on the payment button, and the money is transferred to the scammer. The victim is then redirected to the information page about the freebie. The victim essentially made a valid payment done via a scam webpge.

What Does the X-Frame-Options Header Do?

To protect against clickjacking, the webserver or application can send a response with HTTP header X-Frame-Options. This can be done at webserver level or application level. In this case, we will show you how to do it using web servers Nginx or Apache, and from a Flask application.

X-Frame-Options Directives

The possible directives for X-Frame-Options are:

X-Frame-Options: DENY
X-Frame-Options: SAMEORIGIN

There was a third directive:

X-Frame-Options: ALLOW-FROM origin

But this directive has been made obselete.

X-Frame-Options: DENY

This directive is used to prevent the webpage load fail if called from within an iframe.

X-Frame-Options: SAMEORIGIN

This directive is used to make the webpage load and load only if all parent and ancestor frames are from the same domain itself.

How To Set X-Frame-Options In Nginx

To configure Nginx to send the X-Frame-Options header with SAMEORIGIN, include this line of code in nginx's http block or the virtual host's server block:

add_header x-frame-options "SAMEORIGIN" always;

To deny:

add_header x-frame-options "DENY" always;

How To Set X-Frame-Options In Apache

To configure Apache to send the X-Frame-Options header with SAMEORIGIN for all pages, include this line of code in Apache's http block:

Header always set X-Frame-Options "SAMEORIGIN"

To deny:

Header set X-Frame-Options "DENY"

How To Set X-Frame-Options In Flask Applications

If you have a Python Flask application running and it returns the headers directly use this code, you can add it in an after_request decorator.

To enable X-Frame-Options for same origin:

@app.after_request
def after_request(response):
    response.headers['X-Frame-Options'] = 'SAMEORIGIN'
    return response

To enable X-Frame-Options and block frames from embedding it:

@app.after_request
def after_request(response):
    response.headers['X-Frame-Options'] = 'DENY'
    return response

Complete Flask Application That Uses HSTS and X-Frame-Options

This is a fully working Flask program that has enabled HSTS and X-Frame-Options (same origin).

app.py

from flask import Flask

app = Flask(__name__)
@app.after_request
def after_request(response):
  response.headers['Strict-Transport-Security'] = 'max-age=31536000; includeSubDomains; preload'
  response.headers['X-Frame-Options'] = 'SAMEORIGIN'
  return response

@app.route("/")
def index():
  return 'Hello'

if __name__ == "__main__":
  app.run()

Output of curl -I

$ curl -I http://127.0.0.1:5000
HTTP/1.1 200 OK
Server: Werkzeug/3.0.1 Python/3.12.4
Date: Mon, 26 Aug 2024 20:52:34 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 5
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
X-Frame-Options: SAMEORIGIN
Connection: close

How To Set X-Frame-Options In NodeJS applications

If you have a NodeJS application running on ExpressJS and it returns the headers directly, you can use Helmet library. This code should work:

const helmet = require("helmet");
...
app.use(
  helmet({
    xFrameOptions: { action: "sameorigin" },
  }),
);

How To Test If a Website is Sending X-Frame-Options Header

To test if a website (say aruljohn.com) is sending X-Frame-Options, run this on the command line:

curl -sI https://aruljohn.com | grep -i 'x-frame'

The output will be like this:

$ curl -sI https://aruljohn.com | grep -i 'x-frame'
x-frame-options: SAMEORIGIN

If the webserver or web application does not have X-Frame-Options set, the response of this command will be blank.

Did this work for you?

If this did not work for you or you have any questions, always feel free to contact me and I will try to reply within 24-48 hours.

Related Posts

If you have any questions, please contact me at arulbOsutkNiqlzziyties@gNqmaizl.bkcom. You can also post questions in our Facebook group. Thank you.

Disclaimer: Our website is supported by our users. We sometimes earn affiliate links when you click through the affiliate links on our website.

Last Updated: August 26, 2024.     This post was originally written on August 26, 2024.