@travetto/auth

4.0.0 • Public • Published

Authentication

Authentication scaffolding for the Travetto framework

Install: @travetto/auth

npm install @travetto/auth

# or

yarn add @travetto/auth

This module provides the high-level backdrop for managing security principals. The goal of this module is to be a centralized location for various security frameworks to plug into. The primary contributions are:

  • Standard Types
  • Authentication Contract
  • Authorization Contract
  • Common security-related utilities for
    • Checking permissions
    • Generating passwords

Standard Types

The module's goal is to be as flexible as possible. To that end, the primary contract that this module defines, is that of the Principal Structure.

Code: Principal Structure

export interface Principal<D = { [key: string]: any }> {
  /**
   * Primary identifier for a user
   */
  id: string;
  /**
   * Date of expiration
   */
  expiresAt?: Date;
  /**
   * Date of issuance
   */
  issuedAt?: Date;
  /**
   * Max age in seconds a principal is valid
   */
  maxAge?: number;
  /**
   * The source of the issuance
   */
  issuer?: string;
  /**
   * Supplemental details
   */
  details: D;
  /**
   * List of all provided permissions
   */
  permissions?: string[];
}

As referenced above, a Principal Structure is defined as a user with respect to a security context. This can be information the application knows about the user (authorized) or what a separate service may know about a user (3rd-party authentication).

Authentication

Code: Authenticator

export interface Authenticator<T = unknown, P extends Principal = Principal, C = unknown> {
  /**
   * Allows for the authenticator to be initialized if needed
   * @param ctx
   */
  initialize?(ctx: C): Promise<void>;

  /**
   * Verify the payload, ensuring the payload is correctly identified.
   *
   * @returns Valid principal if authenticated
   * @returns undefined if authentication is valid, but incomplete (multi-step)
   * @throws AppError if authentication fails
   */
  authenticate(payload: T, ctx?: C): Promise<P | undefined> | P | undefined;
}

The Authenticator only requires one method to be defined, and that is authenticate. This method receives a generic payload, and a supplemental context as an input. The interface is responsible for converting that to an authenticated principal.

Example

The JWT module is a good example of an authenticator. This is a common use case for simple internal auth.

Authorization

Code: Authorizer

export interface Authorizer<P extends Principal = Principal> {
  /**
   * Authorize inbound principal, verifying it's permission to access the system.
   * @param principal
   * @returns New principal that conforms to the required principal shape
   */
  authorize(principal: Principal): Promise<P> | P;
}

Authorizers are generally seen as a secondary step post-authentication. Authentication acts as a very basic form of authorization, assuming the principal store is owned by the application.

The Authorizer only requires one method to be defined, and that is authorizer. This method receives an authenticated principal as an input, and is responsible for converting that to an authorized principal.

Example

The Data Modeling Support extension is a good example of an authenticator. This is a common use case for simple internal auth.

Overall, the structure is simple, but drives home the primary use cases of the framework. The goals are:

  • Be able to identify a user uniquely
  • To have a reference to a user's set of permissions
  • To have access to the principal

Common Utilities

The AuthUtil provides the following functionality:

Code: Auth util structure

import crypto from 'node:crypto';
import util from 'node:util';
import { AppError, Util } from '@travetto/base';
const pbkdf2 = util.promisify(crypto.pbkdf2);
/**
 * Standard auth utilities
 */
export class AuthUtil {
  /**
   * Generate a hash for a given value
   *
   * @param value Value to hash
   * @param salt The salt value
   * @param iterations Number of iterations on hashing
   * @param keylen Length of hash
   * @param digest Digest method
   */
  static generateHash(value: string, salt: string, iterations = 25000, keylen = 256, digest = 'sha256'): Promise<string>;
  /**
   * Generate a salted password, with the ability to validate the password
   *
   * @param password
   * @param salt Salt value, or if a number, length of salt
   * @param validator Optional function to validate your password
   */
  static async generatePassword(password: string, salt: number | string = 32): Promise<{ salt: string, hash: string }>;
}

roleMatcher is probably the only functionality that needs to be explained. The function extends the core allow/deny matcher functionality from Base's Util class.

An example of role checks could be:

  • Admin
  • !Editor
  • Owner+Author The code would check the list in order, which would result in the following logic:
  • If the user is an admin, always allow
  • If the user has the editor role, deny
  • If the user is both an owner and an author allow
  • By default, deny due to the presence of positive checks

Package Sidebar

Install

npm i @travetto/auth

Homepage

travetto.io

Weekly Downloads

593

Version

4.0.0

License

MIT

Unpacked Size

11.8 kB

Total Files

9

Last publish

Collaborators

  • arcsine