Basic authentication : Vanilla JS
Tags: javascript, basicauthentication, tutorial
Published: 2021-07-16 23:26:16

Ever thought of how websites and web server protect their secret behind the door well it's not much different than the real world 
<ol>
<li>
You buy a security system 
</li>

<li>
You lock your stuff behind the security system 
</li>


</ol>

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 : 

<ul>
<li>
  <b>Basic Authentication</b>
</li>

<li>
Bearer/Token Authentication
</li>


<li>
OAuth Authentication
</li>


</ul>


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

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

once initialized install express from npm and add to the dependency list
<code>npm install express --save</code>

once express is installed make a app.js file in the root directory and load the express module
<code>
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}`)
});
</code>

we also created our first route the root route 

run your node server by 
<code>node app.js</code>

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cj9tuzbioqecorsr9kc6.png)

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

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

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

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

<code>
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")


}
</code>

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

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sok82r6ajq4xso5zcs3a.png)


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 <Base 64 encoded string>"

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

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

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


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 

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d665tlrvexnsrxnzyue4.png)


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

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gmim00f2oa2zqfwrcibm.png)

**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