Open In App

Password Protect a Static Website

Improve
Improve
Like Article
Like
Save
Share
Report

Static websites are on rising again, In the early days of Internet HTML, CSS with some JavaScript is all the website, since then a number of Backend Frameworks like Django, Larvel, Ruby on Rails have been developed along with looks like WordPress which now powers one-third of websites have been also gained popularity. Website Builders are also exploded so that anyone can have webpages whether they have technical skills or not. 

The development of all these new technologies also gave new security challenges. Poorly coded Authentication Backends, Passwords Reuse, Limited usage of Multi-Factor Authentication to outdated WordPress plugins, vulnerable JavaScript libraries, and unreliable hosting providers made Security a major aspect of the web. As developers always tend to solve existing problems to create new ones to solve in the future, Most of the developers went back to old good static websites but in a different manner.

JAMstack:

JAM stands for JavaScript API’s and Markup. The term was coined by Mathias Biilmann founder of Netlify(A popular JAMstack host also pioneer of JAMstack). In this word, “JAM stack is a modern website architecture based on Client-Side JavaScript, reusable API’s and prebuilt Markup”

  • JavaScript provides interactability and Dynamic nature for the website
  • API’s helps to add some Server Side abilities securely
  • Markup helps to generate a website from source files such as markdown files, HTML templates, and CSS using a Static Site Generator like Jekyll, Gatsby, Hugo, and more

The most popular reasons for adaptation of JAMstack by developers is

  • Faster performance because there is no server-side rendering and most of the HTML already pre-built, Webpages load faster using CDN
  • Since there is no server to process it itself makes webpages More Secure
  • Less expensive than normal websites, most of the Static Hosting providers like Netlify, Vercel, Render, GitHub Pages, GitLab Pages, Cloudflare Pages have a free plan which is more than enough for most the developers
  • Scalability is easy because all it needs is to upgrade the bandwidth we are paying

But one of the most useful we generally miss while using Static Websites is password protection while many providers offer password protection it generally comes with a price but again we are developers we always try to find a way out. Static websites include JavaScript we will also use a JavaScript library Staticrypt by Robinmoisson to protect our static website.

This article requires nodejs and npm to be installed on your computer, you can learn more about it from Installation of Node.js on Linux and Installation of Node.js on Windows

Installing staticrypt:

StatiCrypt generates a static, password-protected page using AES -256 by utilizing a crypto-js library that can be decrypted in-browser you can upload the encrypted page as a normal file in your website and when the file is requested the JavaScript will prompt users for a password, decrypt the page and load your HTML.

Open your PowerShell or terminal and install staticrypt using npm

npm -g install staticrypt

For this article, we have taken an HTML template, in general, the website without password protection loads normally like below

HTML




<!DOCTYPE html>
<html lang="en">
  
<head>
    <meta charset="utf-8">
    <meta name="viewport" 
          content="width=device-width,
                   initial-scale=1.0">
    <link href=
          rel="stylesheet" 
          integrity=
"sha384-BmbxuPwQa2lc/FVzBcNJ7UAyJxM6wuqIj61tLrc4wSX0szH/Ev+nYRRuWlolflfl" 
          crossorigin="anonymous">
    <title>Password Protect Site using staticrypt</title>
</head>
  
<body class="text-center">
    <div class="jumbotron text-center">
        <h1>Welcome to GeeksForGeeks</h1>
    </div>
    <div class="card-body">
        <h4 class="h4 card-title">
            This article explains a simple technique
             to password protect static websites
        </h4>
    </div>
    <div class="jumbotron text-center">
        <h6 class="h6 card-text">Thank You for Reading</h6>
    </div>
</body>
  
</html>


Without Password Protection

Now go into your project directory and open terminal from the directory and type in the below command:

staticrypt index.html geeksforgeeks -o index.html

The command is as follows

  • staticrypt is the name of the library
  • index.html is the index file of our website, the file we need to encrypt
  • geeksforgeeks is the password for the website, you can use any password you want
  • -o index.html is a way of telling to name the output file as index.html

As soon as we run the above command we would be asked for a password while accessing the website

password prompt

As soon as we give the right password we will be given access to that page

If you don’t want the default password template to create your own HTML form and add the following JavaScript.

Javascript




var keySize = 256;
var iterations = 1000;
function access(protectedText, pass) {
    var salt = CryptoJS.enc.Hex.parse(protectedText.substr(0, 32));
    var iv = CryptoJS.enc.Hex.parse(protectedText.substr(32, 32));
    var protected = protectedText.substring(64);
  
    var key = CryptoJS.PBKDF2(pass, salt, {
        keySize: keySize / 32,
        iterations: iterations,
    });
  
    var decrypted = CryptoJS.AES.decrypt(protected, key, {
        iv: iv,
        padding: CryptoJS.pad.Pkcs7,
        mode: CryptoJS.mode.CBC,
    }).toString(CryptoJS.enc.Utf8);
    return decrypted;
}
  
document.getElementById(
  "static-pass-form").addEventListener("submit", function (e) {
    e.preventDefault();
  
    var passphrase = document.getElementById("static-pass").value,
        // Add encrypt string of the Passphrase
        protectedText ="Encrypt Passphrase",
        protectedHMAC = protectedText.substring(0, 64),
        protectedHTML = protectedText.substring(64),
        decryptedHMAC = CryptoJS.HmacSHA256(
          protectedHTML, CryptoJS.SHA256(
            passphrase).toString()).toString();
    // If passphrase is wrong
    if (decryptedHMAC !== protectedHMAC) {
        alert("Bad passphrase!");
        return;
    }
  
    var plainHTML = access(protectedHTML, passphrase);
  
    document.write(plainHTML);
    document.close();
});


Replace the protectedText value with the value of your HTML, You can get the HTML value using this online tool. The full custom HTML template code is below

HTML




<!DOCTYPE html>
<html lang="en">
  
<head>
    <meta charset="utf-8">
    <meta name="viewport" 
          content="width=device-width, initial-scale=1.0">
    <link href=
          rel="stylesheet" 
          integrity=
"sha384-BmbxuPwQa2lc/FVzBcNJ7UAyJxM6wuqIj61tLrc4wSX0szH/Ev+nYRRuWlolflfl" 
          crossorigin="anonymous">
    <title>Password Protect Site using staticrypt</title>
    <script src=
            integrity=
"sha384-lp4k1VRKPU9eBnPePjnJ9M2RF3i7PC30gXs70+elCVfgwLwx1tv5+ctxdtwxqZa7" 
            crossorigin="anonymous"></script>
</head>
  
<body class="text-center">
    <form id="static-pass-form">
        <div class="mb-3">
            <label for="password" 
                   class="form-label">Password</label>
            <input id="static-pass"
                   type="password" 
                   class="form-control"
                   id="Password"
                   aria-describedby="PasswordHelp">
            <div id="PasswordHelp" 
                 class="form-text">
                 You need Password to access the page.
                </div>
        </div>
        <input type="submit" 
               class="btn btn-primary"
               value="Access" />
    </form>
    <script>
        var keySize = 256;
        var iterations = 1000;
  
        function access(protectedText, pass) {
            var salt = CryptoJS.enc.Hex.parse(protectedText.substr(0, 32));
            var iv = CryptoJS.enc.Hex.parse(protectedText.substr(32, 32))
            var protected = protectedText.substring(64);
  
            var key = CryptoJS.PBKDF2(pass, salt, {
                keySize: keySize / 32,
                iterations: iterations
            });
  
            var decrypted = CryptoJS.AES.decrypt(protected, key, {
                iv: iv,
                padding: CryptoJS.pad.Pkcs7,
                mode: CryptoJS.mode.CBC
            }).toString(CryptoJS.enc.Utf8);
            return decrypted;
        }
  
        document.getElementById(
            'static-pass-form').addEventListener('submit', function(e) {
            e.preventDefault();
  
            var passphrase = document.getElementById('static-pass').value,
                protectedText = "Encrypt Passphrase",
                protectedHMAC = protectedText.substring(0, 64),
                protectedHTML = protectedText.substring(64),
                decryptedHMAC = CryptoJS.HmacSHA256(
                    protectedHTML, CryptoJS.SHA256(
                        passphrase).toString()).toString();
  
            if (decryptedHMAC !== protectedHMAC) {
                alert('Bad passphrase!');
                return;
            }
  
            var plainHTML = access(protectedHTML, passphrase);
  
            document.write(plainHTML);
            document.close();
        });
    </script>
</body>
  
</html>


custom template

If you use a default template or custom template, you will get your original HTML if you enter the correct password

Decrypted page



Last Updated : 11 Apr, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads