npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@horanet/hauth

v1.0.2

Published

Web authentication and authorization module for humans and devices with PG database

Downloads

35

Readme

hauth: Web authentication and authorization module for humans and devices

This hauth package provides secured client password-based authentication and URL-based access control features, that express-based web applications can reuse without rewriting most frequently used authentication flows.

Introduction

This module is aimed at authenticating web users as well as devices. The use of this module assumes that:

  • the app is powered by express
  • the app can connect to a Postgres database, and has right to create tables on that database (if not, the tables can be created by hand)

Features

Password Authentication

If a client makes a request to a path for which the app expects authentication, the app sends an HTTP response with a 401 status code, a reason phrase indicating an authentication error, and a WWW-Authenticate header.

The client can then submit login credentials in either request body, or request header using HTTP Basic Authentication with Authorization header:

Authorization: Basic login:password

Role-based Access Control

Hauth manages access rules based on URLs path (without query string) and on roles. Each user can be assigned one role. Access rules look like:

'/node_modules': 'skip',    // disable access control => no authentication required
'\.css$':        'skip',    // as same - URLs can be expressed with regex
'/app':          'allow',   // allowed to any authenticated user
'/reserved':     ['admin'], // access granted only to users with role 'admin'
'/':             'deny',    // forbid everything which is not allowed

See below accessRules to get more informations about access rules format.

By default, if no access rule matches, access is allowed to all authenticated users.

Accessing User Data

The app can retrieve user data in req.user field.

Custom Login and Forbidden Pages

In case of missing credentials or access denied, Hauth will respond with 401 or 403 ; else, the response is managed by the application.

Besides, it is possible to manage custom 401 or 403 response, for example in order to provide an authentication form or a "Forbidden" page.

Session Storage

  • User data are stored in a JSON Web Token (JWT), so the session data is stored only on client's side, and not in the database.
  • Ability to configure JWT key, algorithm and expiration time
  • It is advised to set a JWT key: indeed, if not set a random key is computed at each server startup, so after each startup, JWT previously delivered are not valid anymore and users must reauthenticate.

Passwords Stored Hashed

Salted passwords are hashed with scrypt by scrypt-pwd.

Force Password Change at Next Login

Intended for devices, in case we need to change password (which the device uses to authenticate itself with the app) for security reasons. The module can generate the Next-Password, and the app will include this Next-Password in the response header after a sucessfull authentication, from the next time, the device must use this Next-Password to authenticate.

Account Management

Users can be added, deleted, modified (updating its role, name, changing password, etc.) easily via the exposed functions.

Automatic Account Generation

User accounts can be generated and their details are filled properly in the hauth_user and hauth_role by defining in the configuration.

Default Accounts

The default user accounts are created only at the first use of the module, right after the creation of hauth_user and hauth_role tables, so we always have default accounts ready to log in (to avoid the situation where there is no account). These accounts can be deleted after.

Usage

Create an express app, require the module hauth, init it with db and config parameters, and enjoy!

const express = require('express');
const app = express();

const pg = require('pg');
const db = new pg.Pool( /* PG params */ );
const config = { /* cf doc below */ };
const hauth = require('@horanet/hauth');
hauth.init(config, db);

app.use('/hauth/login', hauth.getCookie);
app.use('/hauth/logout', hauth.delCookie);
app.use('/', hauth.control);

app.use( /* app code */ );
app.listen(port, () => { /* ... */ });

For more features, look at the example provided.

PG tips

Assume the database parameters are as follows:

host: 'localhost',
port: 5432,
database: 'test',
user: 'testuser',
password: 'testpass',

one can create the database using psql:

sudo -u postgres psql
postgres=# CREATE DATABASE test;
postgres=# CREATE USER testuser WITH ENCRYPTED PASSWORD 'testpass';
postgres=# GRANT ALL PRIVILEGES ON DATABASE mydb TO testuser;

With the correct params to connect to the created PG database, the module will automatically creates two tables (if they do not exist): hauth_user and hauth_role.

Config parameters

Module hauth takes in two sets of parameters:

const hauth = require('@horanet/hauth');
hauth.init(params, db);

where db is a database handle, for example

const db = new pg.Pool({
  host: 'localhost',
  port: 5432,
  database: 'test',
  user: 'testuser',
  password: 'testpass'
});

and params is an object containing the configuration parameters (all optional):

cookiename

the default value is hauth

JWT parameters

as defined in jsonwebtoken module

  • jwt_key: key used to cipher JSON web tokens, optional ; if not defined,randomly generated at each server startup
  • jwt_alg: algorithm used for signing JWT, default value is HS256
  • jwt_exp: expiration time for JWT, default 2h for 2 hours

roles

an array with the name of the roles. Each user can be assigned one role granting access to some URLs according to accessRules. For example, roles = ['admin', 'basic_user']

accessRules

dictate the behavior of the control function, according to the URLs, with the following format:

<pattern>: <keyword> or <list of accepted profiles> 

where pattern is:

  • a path, matching the starting of the request path (hence, starting with /), e.g. '/files/'
  • or a regex string matching a part of the request path, e.g. '\.css$' (a pattern is recognized as a regex by the fact that it does not start with /)

The keywords are:

  • allow: allowed access to any authenticated user
  • deny: access forbidden
  • skip: allowed access without authentication

These rules are tested in the order they are listed, until a rule matches the request path.

If no access rule matches the request path, the default rule is allow. So, in order to forbid anything that is not explicitly allowed, you should end the access rules with the rule '/': 'deny'

on401

A function to provide custom response if user authentication is required (typically used to send an authentication form)

on403

A function to provide custom response in case of access denied

onLogout

A function to provide custom response when the user logs out

autocreate

A function to make possible for an unregistered client to create its own accounts. If this function is defined, if an unknown client provides username and password, it makes it possible to check the credentials and to run some more code; if this function returns a non-null object describing an account, Hauth will create the account in hauth_user and deliver a new password (in a 'X-Next-Password' Header).

For example,

  autocreate: async function(login, pwd, db, request_headers) {
    if (pwd === 'secret') { // this magic password allows to create any admin account
      await db.query('INSERT INTO ...'); // you can add some extra processing
      return {login: login, name: login, role: 'admin'}
    }
  }

The autocreate function extra processing should be idempotent. Indeed, a common way to reset client credentials is to remove the corresponding record in haut_user, which induces to re-run the autocreate process. Besides, the client might fail to catch the next password, and thus re-run the autocreate process.
Most of the SQL INSERT requests run in that function should finish with on conflict do nothing.

defaultUsers

An array of users to be created along with tables hauth_users and hauth_roles. This is intended for initing apps; These accounts can then be modified or deleted, and will not be recreated at each server startup.

APIs

This hauth module exposes the following functions:

init

Initialize the module. This function takes in the config and db parameters ; it creates the two tables hauth_role and hauth_user if necessary (and thus fills the default users), then fill in the roles defined in config.

control

Runs authentication and access control

allowed

Function allowed(role, url): this function return True if a user with rule <rule> is authorized to access <url>.

getCookie

Sign and verify token using jsonwebtoken module.

delCookie

Delete cookie (so as to log out the current user).

getUser

Given a login, returns a user profile, with password and next_password

  • Input parameter login (string)
  • Return an array [user, password, next_password] with
    • user: a JSON object containing all user data, except password and next_password
    • password: a string, or null if not defined
    • next_password: a string, or null if not defined

addUser

Add a single user to table hauth_user

  • Input parameter user: a JSON object containing user's information. For example:
{"login": "admin", "name": "Administrator", "role": "admin", "password": "admin"}
  • Not all information are required, if a required field is missing, default information will be filled.

delUser

Delete a user from table hauth_user:

  • Input parameter user: a JSON object containing user's information
  • Require field: user.login
  • User with login will be deleted
  • Return pass value: true in case the DELETE query was succesfull, false otherwise.

modUser

Modify existing user in table hauth_user:

  • Input parameter user: a JSON object containing user's information
  • Require field: user.login
  • Information of user with login will be updated according to the input fields
  • Return pass value: true in case the UPDATE query was succesfull, false otherwise.

Example

To run the example (the script located in ./example/index.js):

npm install
npm run example

To check the currently logged in user, use the path localhost:3000/whoami

Test

FAQ