Skip to content

Authentication

Susanna Nevalainen edited this page Dec 5, 2020 · 6 revisions

Things to take into account when designing full-stack node.js authentication system

πŸͺ Cookies and sessions

Cookies are tool to save data on client-side (in browser)

  • Pro: Cookies can be used to share data globally without exposing global data to users.
  • Con: You can manipulate cookies inside browser so sensitive data should not be stored in cookies but works for analytics tracking etc
res.setHeader('Set-Cookie', 'loggedIn=true; Max-Age: 1000')

req.get('Cookie')

Sessions are tool to save data on server-side. Use sessions for sharing data across requests scoping data for a specific user without exposing data for other users

npm install --save express-session
npm install --save connect-mongodb-session

app.js

const express = require("express");
app.use(
  session({
    secret: "my secret",
    // saves only if sth is changed
    resave: false,
    saveUninitialized: false,
    store: store
  })
);

authenticate user (login)

req.session.isLoggedIn = true;
      req.session.user = user;
      req.session.save(err => {
        console.log(err);
        res.redirect("/");
      });

destroy session after user disconnected (logout)

req.session.destroy()

πŸ”‘ bcrypt - Password encryption

bcrypt is a npm library to help you hash passwords. In production environment, one should never have passwords as human readable strings to ensure security.

const bcrypt = require("bcryptjs");

create hashed password when saving pw to db (12 = number of hashing rounds)

bcrypt.hash(password, 12)

compare hashed password when user logging in

bcrypt.compare(password, user.password);

πŸ‘Š csurf - protection agains CSRF attacks

Cross-Site Request Forgery (CSRF) is an attack that forces an end user to execute unwanted actions on a web application in which they're currently authenticated. This can happen for example when user clicks a link in email that takes to another fake but real looking view and this fake view sends request to real server.

csurf adds CSRF token into views and on the backend accepts only requests that have valid token to avoid intruders using external views to send requests.

app.js

const csrf = require("csurf");
...
const csrfProtection = csrf();

app.use(csrfProtection);

// Access local variables on each view that is rendered
app.use((req, res, next) => {
  res.locals.isAuthenticated = req.session.isLoggedIn;
  res.locals.csrfToken = req.csrfToken();
  next();
});

controller files rendering views so that csrfToken is accessible in view

res.render("shop/index", {
  prods: products,
  pageTitle: "Shop",
  path: "/",
  isAuthenticated: req.session.isLoggedIn,
  csrfToken: req.csrfToken()
});

Add hidden input with csrfToken inside each form in the app, the name of input must be _csrf as csurf will look for this name in the inputs

 <input type="hidden" name="_csrf" value="<%= csrfToken %>" />

Clone this wiki locally