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
  • You buy a security system
  • 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}`)
    });
    we also created our first route the root route
    run your node server by
    node app.js
    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"})
    })
    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")
    
    
    }
    notice how we delibrately provided a wrong password
    let's see what response we get in browser
    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>
    and the javascript to prevent reloading of the page and execute a fetch request from behind
    document.addEventListener("submit" , (event)=>{
                      event.preventDefault()
                   })
    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")
                   })
    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")
    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")
          })
    })
    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(':')
    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()
        }
    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")
                       }
                   })
    let's try out our app in the browser
    I have provided the inputs with correct secrets let's submit the form
    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

    16

    This website collects cookies to deliver better user experience

    Basic authentication : Vanilla JS