0.2.0 • Published 6 years ago

@laosdirg/security v0.2.0

Weekly downloads
-
License
MIT
Repository
github
Last release
6 years ago

@laosdirg/security

A bunch of helpers for securing javascript applications

NPM Version NPM Downloads

import {
  hashPassword,
  verifyPassword,
  generateToken,
  splitToken,
  verifyToken,
} from '@laosdirg/security.js';

function signUp(request, response) {
  // extract provided credentials from request
  const { username, passwordPlaintext } = request.body;
  // create hashed password
  const passwordHash = hashPassword(passwordPlaintext);
  // persist user to storage with HASHED password
  User.create({ username, passwordHash });
  // optionally log in user right away, see below
  return logIn(request, response);
}

function logIn(request, response) {
  // extract provided credentials from request
  const { username, passwordPlaintext } = request.body;
  // fetch corresponding user from storage
  const { userId, passwordHash } = User.get({ username });
  // verify password against stored hash
  if (!verifyPassword(passworHash, passwordPlaintext)) {
    throw new Error('Unauthorized');
  }
  // generate fresh token
  const { token, selector, verifierHash } = generateToken();
  // store with HASHED verifier in database and user reference
  Token.create({ selector, verifierHash, userId });
  // send unhashed token to user
  response.cookie('token', token);
}

function currentUser(request, response) {
  // extract token (from cookie, authorization header, etc.)
  const { token } = request.cookies;
  // split token into selector and plaintxt verifier
  const { selector, verifierPlaintext } = splitToken(token);
  // use selector to fetch token from storage
  const { verifierHash, userId } = Token.get({ selector });
  // verify the token based on verifier
  if(!verifyToken(verifierHash, verifierPlaintext)) {
    throw new Error('Unauthorized');
  }
  // fetch corresponding user and send as response
  const user = User.get({ userId });
  response.send(user);
}

Installation

$ npm install @laosdirg/security

API

Passwords

Passwords are be hashed with a salt, and stored with the parameters that generated the password.

hashPassword(plaintext: string)

Returns string hashed password.

verifyPassword(hash: string, plaintext: string)

Returns boolean whether verification succeeded.

Tokens (split tokens)

Tokens have many uses: user sessions, password recovery emails, etc., usually they are provided upon presenting some other kind of credentials like a username and password.

However, tokens need to be treated like passwords. If an attacker gains with read-only access to your token database and they are stored as-is, the attacker can steal and use all of your tokens.

Following best practices from paragonie, our approach splits tokens into a username-like and password-like part, and hashes the password-like part. The entire unhashed token can be sent to the user, but the unhashed token should never be stored in your database.

The selector is to prevent leaking timing information.

generateToken()

Returns { token: string, selector: string, verifierHash: string } split token.

splitToken(token: string)

Returns { selector: string, verifierPlaintext: string} selector and verifier in dict.

verifyToken(hash: string, plaintext: string)

Returns boolean whether verification succeeded.

Usefull tools

  • helmet for setting various headers in express apps.
  • zxcvbn estimating password strength (display this to users during signup)

Additional reading

How to Safely Store Your Users' Passwords in 2016

https://paragonie.com/blog/2016/02/how-safely-store-password-in-2016

Implementing password reset

https://paragonie.com/blog/2016/09/untangling-forget-me-knot-secure-account-recovery-made-simple

TL;DR:

  • DO:
    • Make automated password resets optional, and opt-in
    • Send a short-lived URL to their email address which contains a random token (generated by a CSPRNG)
    • Use a split-token strategy to mitigate side-channels and database leaks
    • Allow users to upload a PGP public key, and if it's available, use it encrypt the recovery URL
  • DO NOT:
    • Email the user their old password
    • Change the user's password for them and email them the new one
    • Rely on security questions/answers, which most attackers can guess for their targets

Additional security

Cross-Site Scripting (XSS)

Cross-Site Request Forgery

Cross-Site Request Forgery (CSRF/XSRF) is a type of attack that occurs when a malicious web site, email, blog, instant message, or program causes a user's web browser to perform an unwanted action on a trusted site for which the user is currently authenticated. The impact of a successful CSRF attack is limited to the capabilities exposed by the vulnerable application. For example, this attack could result in a transfer of funds, changing a password, or purchasing an item in the user's context. In effect, CSRF attacks are used by an attacker to make a target system perform a function via the target's browser without knowledge of the target user, at least until the unauthorized transaction has been committed.

Defense

It is imperative that no XSS vulnerabilities are present to ensure that CSRF defenses can't be circumvented.

The synchronizer token pattern requires the generating of random "challenge" tokens that are associated with the user's current session. These challenge tokens are then inserted within the HTML forms and links associated with sensitive server-side operations. When the user wishes to invoke these sensitive operations, the HTTP request should include this challenge token. It is then the responsibility of the server application to verify the existence and correctness of this token. By including a challenge token with each request, the developer has a strong control to verify that the user actually intended to submit the desired requests. Inclusion of a required security token in HTTP requests associated with sensitive business functions helps mitigate CSRF attacks as successful exploitation assumes the attacker knows the randomly generated token for the target victim's session. This is analogous to the attacker being able to guess the target victim's session identifier.

License

MIT

0.2.0

6 years ago

0.1.1

7 years ago

0.1.0

7 years ago

0.0.1

7 years ago