-
Notifications
You must be signed in to change notification settings - Fork 0
Authentication
Things to take into account when designing full-stack node.js authentication system
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 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);
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 %>" />