Basic authentication : Vanilla JS

anasaijaz

anasaijaz

Posted on July 16, 2021

Basic authentication : Vanilla JS

Ever thought of how websites and web server protect their secret behind the door well it's not much different than the real world

  1. You buy a security system
  2. You lock your stuff behind the security system

Easy right? Just like there are different types of security system available for real world we have different type of systems for the web too
Some of the popular ones are :

  • Basic Authentication
  • Bearer/Token Authentication
  • OAuth Authentication

Basic Authentication is the oldest of the authentication available it's not much popular now
But before understanding more advanced authentications it's absolute neccesarry

so fire up your node and let's understand the authentication process

Create a folder Tutorial
In here all of our backend code will lie
mkdir Tutorial
initialize the npm using npm init command

once initialized install express from npm and add to the dependency list
npm install express --save

once express is installed make a app.js file in the root directory and load the express module


const express = require("express")
const app = express()

process.env.PORT = 3000

app.get("/" , (req ,res)=>{
    res.status(200).send({"STATUS":"SUCCESS"})
})

app.listen(3000 , ()=>{
    console.log(`STARTED LISTENING ON PORT ${process.env.PORT}`)
});

Enter fullscreen mode Exit fullscreen mode

we also created our first route the root route

run your node server by
node app.js

image

let's lock out root route behind a middle ware function which will first authenticate the user with the secret


const isAuthenticated = (req , res , next)=>{
    next()
}

app.get("/" ,isAuthenticated, (req ,res)=>{
    res.status(200).send({"STATUS":"SUCCESS"})
})

Enter fullscreen mode Exit fullscreen mode

and then modifying the middle ware function to check the user provided credential against the credential stored on the server


const credentials = {secretName:"Anas Aijaz" , secretPassword:"Catsaresosus"}

const isAuthenticated = (req , res , next)=>{
    const [name , password] = ["Anas Aijaz" , "Dogsaresosus"]

    // We will add code here later

    if(name===credentials.secretName && password===credentials.secretPassword){
        // The User is authenticated
        return next()
    }

    // User is not authenticated give a reponse 401
    res.set('WWW-Authenticate', 'Basic realm="Access to Index"')
    res.status(401).send("Unauthorised access")


}

Enter fullscreen mode Exit fullscreen mode

notice how we delibrately provided a wrong password
let's see what response we get in browser

image

Oops you the content is locked now and needs a right secret to open

let's work our way through the front end to take input from the user and send it to the server

create a folder beside the Tutorial folder named client and add a index.html index.js in it

cd ../ && mkdir client && cd client && touch index.html index.js

now create a basic form in the html to take input from the user
and on the pressing of the submit button we will use the fetch API to post the data to the server

 <form>
            <label>username</label>
            <input name="username" type="text"/>


            <label>password</label>
            <input type="password" name="password"/>

            <input type="submit"/>
        </form>

Enter fullscreen mode Exit fullscreen mode

and the javascript to prevent reloading of the page and execute a fetch request from behind

 document.addEventListener("submit" , (event)=>{
                  event.preventDefault()
               })
Enter fullscreen mode Exit fullscreen mode

ok take the input from the user and store it in the variable username and password

now let's focus on creating a fetch request to our server this fetch request will lie inside the submit event listener

 fetch("http://localhost:3000/" , {})
               .then(()=>{})
               .catch(()=>{
                   console.log("an error occured")
               })
Enter fullscreen mode Exit fullscreen mode

the skeleton of fetch request will looks like this

the object passed besides the URI will be the header of our HTTP request

the Header fields of any http request exists in pairs
KEY:VALUE
for example one of the most basic header will be
"Accept: application/json" this will indicate the server that the client will only accept json as a response

just like we can add a "Authorization" key the value of which will be the type of authentication and our email and password separated by a colon ":" encoded in a base64 format so it can be transmitted over the web

"Authorizaton: Basic "

The Headers interface of the fetch api can be conviently used to place these headers in our request

 const headers = new Headers()
 headers.append("Accept" , "application/json")
Enter fullscreen mode Exit fullscreen mode

next task is to encode our username:password string into a base64 string we can use the a method of the root window element

const base64data = window.btoa(${username}:${password})

now it's time to append this to our header with the Basic keyword

const auth = Basic ${base64data}

now our fetch requests look like


fetch("http://localhost:3000/", { headers:headers })
      .then(()=>{})
      .catch(()=>{
         console.log("an error occured")
      })
})

Enter fullscreen mode Exit fullscreen mode

this will send a request to our server with the proper credentials

now on the server side we have to get the request and parse the username and password separately

let's do it in your app.js

in the middle ware function we have to first get the authorization headers and then base64 decode the credential after splitting the BASIC part


 const encodedAuth = (req.headers.authorization || '')
    .split(' ')[1] || '' // getting the part after Basic

 const [name, password] = Buffer.from(encodedAuth, 'base64')
    .toString().split(':')

Enter fullscreen mode Exit fullscreen mode

after splitting the Basic and base64 part we decoded the string and the again splitting it at ":" (remember we added username:password)

as node don't have the window object we have to use the Buffer.from function to decode the string

finally match the input you got from the request with the server secret

 if(name===credentials.secretName && password===credentials.secretPassword){
        // The User is authenticated

        return next()
    }
Enter fullscreen mode Exit fullscreen mode

modify your fetch method to write the document when the request is finally successful

 .then((response)=>{
                   console.log(response)
                   if(response.status == 200){
                       document.write("SUCCESFULL LOGIN")
                   }
               })
Enter fullscreen mode Exit fullscreen mode

let's try out our app in the browser

image

I have provided the inputs with correct secrets let's submit the form

image

Hurray!!!! We are now authenticated by the server and now can access the restricted area

:PS
There are some caveats in our application such as splitting the >string using ":" delimiter will cause unexpected reaction if the >password or username too have a colon you can fix this by >extracting the username and password by REGEX

you can improve this application by issuing a bearer token and >storing it in cookie to access across pages and maintain the >login state but that's the story of another day :)

further reading

https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies

https://medium.com/@dckalubowila25132/jwt-bearer-token-authentication-for-express-js-5e95bf4dead0

💖 💪 🙅 🚩
anasaijaz
anasaijaz

Posted on July 16, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

Basic authentication : Vanilla JS
javascript Basic authentication : Vanilla JS

July 16, 2021