---
title: "Deter Clickjacking When You Can't Set Security Headers By Using Javascript"
date: 2024-01-05T10:05:00-05:00
author: John Morton
canonical_url: "https://supergeekery.com/blog/deter-clickjacking-when-you-cant-access-headers-iframe-javascript"
section: Blog
---
# Deter Clickjacking When You Can&#039;t Set Security Headers By Using Javascript

*January 5, 2024* by John Morton

![Dont clickjack me](https://static.supergeekery.com/site-assets/dont-clickjack-me.jpg)

In this post we'll talk about clickjacking, how to protect your site visitor's with robust soltuions, and a fallback method when you're unable to do it the normal way. The need for this fallback solution is what inspired by a real-world scenario that I faced when a client needed a quick fix while the longer-term solution was implemented. 

## What is clickjacking

How do you protect your users from clickjacking? First, you have to be aware of what clickjacking is. Let's look at the [Mozilla.org documentation](https://developer.mozilla.org/en-US/docs/Glossary/Clickjacking) for a defintion. 

> Clickjacking is an interface-based attack that tricks website users into unwittingly clicking on malicious links. In clickjacking, the attackers embed their malicious links into buttons or legitimate pages in a website.

It's easier to understand what the means through an made-up example.

### An example of clickjacking

Imagine this webpage at `supergeekery.com` was being hijacked from a similar but malicious url, `suppppergeeeekery.com`. The malicious url could embed the legitimate page within an iframe and then add additional content *on top* of the original content. For example, the internet-bad-guy could add a button to the page that says "Sign up and get $1,000,000!" When a user clicks on the button, a form would appear that collected the user's data for nefarious purposes. 😠

## The X-Frame-Options header

As the creator of `supergeekery.com`, it's easy for me to stop internet-bad-guys from embedding `supergeekery.com` into an iframe by setting the site's headers. The screenshot below shows the headers that have been set on this webpage. There are quite a few headers, but I've highlighted one in particular called **X-Frame-Options**, which has been set to **SAMEORIGIN**. This header is a rule that a brower will obey that says this webpage can only be used within an iframe on the same domain that it originally exists on.
![Supergeekery iframe options headers](https://static.supergeekery.com/site-assets/supergeekery-iframe-options-headers.png)
*The X-Frame-Options header set to &quot;SAMEORIGIN&quot;*
## The Content-Security-Policy header

Modern browsers support a powerful and nuanced option with the [**Content-Security-Policy**](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy) header. This is also an effective solution, but this headers is more complicated to set up. I don't need that level of complexity so I still use the **X-Frame-Options** header. Use which ever solution works best for you.

## Setting headers

Setting headers can be complicated because they are set on a server level and are dependent on how you're building your site. That means I can't show you how to set headers for your project, but I can suggest some next steps. You might configure them in your [Apache](https://httpd.apache.org/docs/trunk/mod/mod_headers.html) configuration, your [Nginx](https://www.nginx.com/resources/wiki/start/topics/examples/headers_management/) configuration, or maybe with a dynamic server side language, like [PHP](https://www.php.net/manual/en/function.header.php) or [Node](https://dev.to/nonunicorn/getting-and-setting-headers-in-nodejs-http-server-3nl7). On this site, I've set them up through my Nginx configuration.

### Testing

You can see your headers in your DevTools, as I showed in the first screenshot. You can also use a testing tool to validate that they're set correctly. Let's take a look at this site in one of the testing tools: https://iframetester.com/?url=https://supergeekery.com
![Supergeekery iframe tester](https://static.supergeekery.com/site-assets/supergeekery-iframe-tester.png)
*SuperGeekery.com, shown in iframetest.com, can&#039;t be embedded in an iframe.*
## A fallback solution

As a developer, you may find yourself in situations where you can't set your headers as you want. This is often because a client's infrustructure is managed in a way that protects that type of access. While you're working on a robust solution, you can still add some protection for your users using Javascript. 

The following Javascript code block can be inserted into your pages and will attempt to prevent a page from being embedded in an iframe on another domain. It will allow your page to be put within an iframe on the same domain. I did that intentionally. You may have valid reason for using an iframe on your own content.
```
<script>
  document.addEventListener("DOMContentLoaded", function () {
    if (top.location !== location) {
      document.body.innerHTML = ''; // Clears the existing content
      var noticeDiv = document.createElement('div'); // Create a new div element
      noticeDiv.innerHTML = 'Warning: This page cannot be embedded on another domain.'; // Set the message
      document.body.appendChild(noticeDiv); // Append the div to the body
    }
  });
</script>
```
I don't intend to suggest that this is all you need to do, but it will help while you get your headers set properly.

---

**Tags:** webdev

## Related Posts

- [Make Javascript module creation easier with Vite and automated GitHub Pages and npm publishing](https://supergeekery.com/blog/make-javascript-module-creation-easier-with-vite-and-automated-github-pages-and-npm-publishing)
- [Auto Print an HTML Page](https://supergeekery.com/blog/auto-print-an-html-pag)
- [Adding Date Validation Logic when Creating an Event in Craft CMS 3](https://supergeekery.com/blog/adding-date-validation-logic-when-creating-an-event-in-craft-cms-3)
