Authentication flow

You should consider whether you want to integrate sign-in and sign-up features with the user service or create a separate Auth service. It is advisable to integrate it into the User service when project is small and have a separate service as the project grows.

Password hashing

Storing passwords as plain text is highly insecure. If a malicious individual gains access to the database, they can easily obtain all user passwords. This poses a significant risk as people often reuse the same email and password combinations across multiple platforms, making it a threat to their entire online presence. Passwords should always be encrypted for security purposes. Use Salt (add random series of letters and numbers in front or behind of the password before hashing it) to make rainbow table attack impossible. When saving into the database, hash the password and Salt together, join the result and the Salt into one string using any special character between. (Example: 020077d.a1g01).

Rainbow table attack
A rainbow table attack is a type of cyber attack used to crack password hashes. It involves precomputing the hashes of commonly used passwords and storing them in a large database known as a rainbow table. When a target hash is obtained, the attacker can look it up in the rainbow table to find the corresponding plaintext password. This method can significantly speed up the process of cracking passwords compared to traditional brute-force methods. Security measures like salting passwords can help defend against rainbow table attacks.

Comparing entered password to the saved password when user signs in

  1. Retrieve the user’s password and salt from the database using their email.
  2. Separate the salt from the password.
  3. Hash the provided password with the salt.
  4. Compare the hashed password with the stored hashed password in the database for authentication.

Sign-up and sign-in example

import {
  BadRequestException,
  Injectable,
  NotFoundException,
} from '@nestjs/common';
import { scrypt as _scrypt, randomBytes } from 'crypto';
import { promisify } from 'util';
import { UsersService } from './users.service';

const scrypt = promisify(_scrypt);
// needed to include it in providers
@Injectable()
export class AuthService {
  constructor(private usersService: UsersService) {}

  async signup(email: string, password: string) {
    // See if email is in use
    const users = await this.usersService.find(email);
    if (users.length) {
      throw new BadRequestException('email in use');
    }

    // Hash the users password
    // Generate a salt
    const salt = randomBytes(8).toString('hex');

    // Hash the salt and the password together
    const hash = (await scrypt(password, salt, 32)) as Buffer;

    // Join the hashed result and the salt together
    const result = salt + '.' + hash.toString('hex');

    // Create a new user and save it
    const user = await this.usersService.create(email, result);

    // return the user
    return user;
  }

  async signin(email: string, password: string) {
    const [user] = await this.usersService.find(email);
    if (!user) {
      throw new NotFoundException('user not found');
    }

    const [salt, storedHash] = user.password.split('.');

    const hash = (await scrypt(password, salt, 32)) as Buffer;

    if (storedHash !== hash.toString('hex')) {
      throw new BadRequestException('bad password');
    }

    return user;
  }
}

Handling cookies

Cookies are primarily utilised for three main purposes:

  1. Session Management: This includes storing information like logins, shopping cart items, game scores, or any other data that needs to be remembered by the server.
  2. Personalization: Cookies are used to save user preferences, themes, and various settings to enhance the user experience.
  3. Tracking: Cookies track and analyze user behavior by collecting data on viewed pages and activities on a website. They help recognize users, store user IDs, provide online shopping carts, remember preferences for future visits, tailor browsing experiences, and deliver targeted ads.

In our scenario, we utilise cookies to store the clientId.