12/15/19

What is Session Authentication?

Intro

I want to post here some post for a simpletons like me, who sometimes discovers basic things about web they didn`t knew. For example - recently i asked myself: "what is exactly session?" and, shame on me - i discovered that i cannot give quick and clear answer. So i publishing here some facts i came upon while searching across the web:

Session

Some data stored at server (variable) which connected to some specific user, and "lives" when this user is connected to server. The old classic way to implement this behavior - by creating a cookie.
cookie - some piece of data that comes from server and stored at browser, it has it unique "id" given by server, and may have some other data (like expiration time). cookie should be sent at headers of each request. Server will check the cookie (or if it present) and this way server will now about user and if he is connected

Implementing Session Authentication using Express

Since express.js is the only server framework i feel comfortable with - i will do all the demonstrations using this framework.
So here is some simple server with '/login' and '/private' apis:


const express = require('express');
const app = express();
const port = 4000;
/* must use cors module for recieve requests from different domains */
app.use(require('cors')())

app.post('/login', (req, res) => res.send({user: 'Lukas'}));

app.get('/private', (req, res) => res.send({products: [{name: 'ZX10R'}]}));

app.listen(port, () => console.log(`Example app listening on port ${port}!`))

Pretty nice & simple, right?

Accessing Api`s from client

We have created a grate piece of software in previous step, but - what worth a server if nobody uses it?
In other words: lets create some client which will consume the our shiny apis!


async function bla() {

    const data = await fetch('http://localhost:4000/login', {
      method: 'POST',
      headers: {'content-type': 'application/json'}
    }).then(data => data.json())

    console.log(`hi ${data.user}!`);
    // passed login lets show some private stuff!
    const productsData = await fetch('http://localhost:4000/private', {
      method: 'GET',
      headers: {'content-type': 'application/json'}
    }).then(data => data.json())
          
   console.log(`product: ${productsData.products[0].name}`)
 
}
bla();

As you can see(if you copied the code correctly) - the data being fetched:

Restricting Private Api`s using session

Currently the '/private' api can accessed by everybody (and it is suppose to be private!), so lets make it accessible only to one who passed the login request:
We will do it using cookie-session npm package.
0. install 'cookie-session' lib (npm i cookie-session)
1. use basic configuration:


const cookieSession = require('cookie-session')
app.use(cookieSession({
    name: 'mysession',
    secret: 'your-secret',
    maxAge: 30 * 60 * 1000 // 1/2 hour
}));

2. we will add some data to our session once user passed login request (this code mimics fetching user details from DB)

app.post('/login', (req, res) => {
    req.session.user = 'Lukas';
    res.send({user: 'Lukas'});
});

3. add some middleware which will block (return 401 response) for someone who tried to access to any(except '/login') api when unauthenticated

app.use((req, res, next) => {
    if (req.url.includes('login')) {
        next();
        return; 
    }

    if (!req.session || !req.session.user) {
        res.clearCookie('mysession');
        res.status(401).send({error: 'unauthorized'});
        res.end();   
    }
});

One more thing! We need modify now also the client code:

async function bla() {
    const productsData = await fetch('http://localhost:4000/private', {
      method: 'GET',
      credentilas: 'include', /* each request should carry the cookie at its headers */
      headers: {'content-type': 'application/json'}
    }).then(data => data.json())
          
   console.log(`product: ${productsData.products[0].name}`)
}
bla();

Also at cors configuration - we need to specify "origin" to be trusted:

app.use(cors({
  origin: 'http://localhost:3000', /* host where you client runs */
  credentials: true,
}));

Now, open the "network" panel of chrome dev tools. You should should see the following:

Tada!!! you just make a client to talk to server using session !!!

Getting started with docker

It is very simple to get started usig docker. All you need to do-is download the docker desktop for your system Once you get docker syste...