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

8/17/19

Deboundce In The Javascript

Intro

I decided to wrote here all the things i know about the "debounce" termin
So: by saying "debounce" people mean - some functionality that blocks multiple event handlers from trigger until some specified time interval (like one second) passed.

Example: scroller, that fires lots of "scroll" events when user scrolling down, should respond only to last scroll event within second (specified time interval) and ignore all the rest of events within that second.

Implementation

The key thing for implementing debounce - is to know about "clearTimeout" method, which cancels the previously scheduled actions:


let timer = null;
const debounce = (fn, delay) => {
  // clean previously scheduled actions
  clearTimeout(timer);
  // scheduled  the last action
  timer = setTimeout(fn, delay);
};

document
  .querySelector("#myInput")
  .addEventListener("input", e =>
    debounce(_ => console.log(e.target.value), 1000)
  );
// you will see only last event appears after the delay

Or, if you want to store "timer" inside the function without polutting global scope:


var debounce = (fn, time, immediate) => {
  let timeout;
  return (...rest) => {
    const [args] = rest;

    const later = () => {
      if (!immediate) {
        timeout = null;
        fn(args);
      }
    };

    const callNow = immediate && !timeout;
    clearTimeout(timeout);
    timeout = setTimeout(later, time);

    if (callNow) {
      fn(args);
    }
  };
};
…

document
  .getElementById("app")
  .addEventListener("input", debounce(handle, 1000));

function handle(e) {
  console.log(e.target.value);
}


8/6/19

Why Do You Need "Set" In Javascript

Lets start with explanation what is set.
In the old times the only way to store some data list was by using array:

const users = ['Moshe','Vasia'];


These days some new players entering the scene:
The Set
It has "add", "delete", "clear" (for remove all the entries) methods

const users = new Set(['Moshe', 'Vasia']);
users.add('Ivan'); // will add one more entry

It also has "has" method for checking if item exists in Set:

console.log(users.has('Ivan')); // will print true

As far as I can see - the most cool feature (and may be a purpose of Set`s creation) - is uniqness: Set will not allow duplicates:

console.log(new Set([1,2,4,3,1])); // will 1,2,4,3

BUT (there must be always a "but")
all those cool features will not help you with following structure: (if the array consist of objects)

const users = new Set([
  {id:'123', name: 'Moshe'},
  {id:'124', name: 'Vasia'},
])

You will not be able to check if somebody with id '123' exist in Set using "has" method:

console.log(users.has('123')); // will be false

Also: it appears that Set not has a support for accessing entries by index And if you want to access first entry you will need to use something like this:

const user = users.values().next().value;
console.log(user); // will print "{id:123, name: 'Moshe'}"

Disappointing!
So, when this "Set" might be needed? you may ask...
The answer I found so far - is following scenario:
Remove duplicates:

const users = [
   {id:123, name: 'Moshe'},
   {id:124, name:'Vasia'},
   {id:125, name:'Ivan'},
   {id:123, name: 'Moshe'}// same Moshe one more time
];
const dedupedIds = Array.from(new Set(users.map(({id}) => id)))
console.log(dedupedIds); // will print 123,124,125

Conclusion

Although Set looks cool and promising - it seems there is not a much cases to use it (As far as I can see now)

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