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

@travetto/auth

v5.0.12

Published

Authentication scaffolding for the Travetto framework

Downloads

652

Readme

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 = AnyMap> {
  /**
   * 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/runtime';
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 Runtime'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