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 🙏

© 2026 – Pkg Stats / Ryan Hefner

auth-cloud-lib

v1.1.3

Published

Authentication and authorization middleware library for Express

Readme

auth-cloud-lib

Express authentication and authorization middleware library.

Exposes four main things:

| Export | Type | Description | |---|---|---| | AuthClient | class | Main entry point — instantiate once, use everywhere | | authClient.checkUserAuthentication | method → middleware | Validates JWT from Authorization header | | authClient.checkUserAuthorization | method → middleware | Enforces an authorization policy | | createRule | namespace | Stateless rule factories | | createPolicy | namespace | Stateless policy composers |


Installation

# The library itself
npm install auth-cloud-lib

# Peer dependency
npm install express

# Install your preferred Redis/Valkey client (pick one)
npm install ioredis
# or
npm install iovalkey

Setup

Instantiate AuthClient once at app startup — before any route is registered — and reuse the instance everywhere.

import { AuthClient } from 'auth-cloud-lib'
import { Redis } from 'ioredis'   // or: import { Redis } from 'iovalkey'
import fs from 'fs'

const authClient = new AuthClient({
  // Your Redis or Valkey client instance
  client: new Redis(process.env.REDIS_URL),

  jwt: {
    // RSA public key — pass the file content, not the path
    publicKey: fs.readFileSync(process.env.RSA_PUBLIC_KEY_PATH, 'utf8'),

    // Must match the `iss` claim used when the tokens were signed
    serviceName: process.env.SERVICE_NAME,
  },

  // Required only when using authClient.createRule.systemPermission
  systemEntityId: process.env.SYSTEM_ENTITY_ID,

  // Optional: e.g. set user on Sentry when authenticated
  onUserAuthenticated: (userId) => Sentry.setUser({ id: userId }),
})

export default authClient

Sentry / monitoring

The library does not depend on Sentry. To associate the authenticated user with Sentry (or any other tool), pass onUserAuthenticated in the config. It is called with the user ID whenever authentication succeeds (any token type).

import * as Sentry from '@sentry/node'

const authClient = new AuthClient({
  ...config,
  onUserAuthenticated: (userId) => Sentry.setUser({ id: userId }),
})

Sentry must be initialized in your app (e.g. Sentry.init({ ... })) before the first request; the library only invokes the callback.


checkUserAuthentication

Validates the JWT in the Authorization: Bearer <token> header.

On success populates req.user with { id, token, sessionId }. On failure throws AuthenticationError (HTTP 401).

import { AuthTokenType } from 'auth-cloud-lib'
import authClient from './authClient.js'

// Protect a route with an access token
router.get('/me',
  authClient.checkUserAuthentication(AuthTokenType.AccessToken),
  (req, res) => res.json({ userId: req.user!.id }),
)

// Protect a token-refresh route
router.post('/refresh',
  authClient.checkUserAuthentication(AuthTokenType.RefreshToken),
  refreshHandler,
)

// Account recovery flow
router.post('/reset-password',
  authClient.checkUserAuthentication(AuthTokenType.RecoveryToken),
  resetPasswordHandler,
)

// Service-to-service exchange token
router.post('/exchange',
  authClient.checkUserAuthentication(AuthTokenType.ExchangeToken),
  exchangeHandler,
)

Token types

| Constant | Value | When to use | |---|---|---| | AuthTokenType.AccessToken | ACCESS_TOKEN | Regular API requests | | AuthTokenType.RefreshToken | REFRESH_TOKEN | Rotating expired access tokens | | AuthTokenType.RecoveryToken | RECOVERY_TOKEN | Account recovery (one-time use) | | AuthTokenType.ExchangeToken | EXCHANGE_TOKEN | Cross-service credential exchange |


checkUserAuthentication + checkUserAuthorization

Authorization always comes after authentication in the middleware chain.

import { createRule, AuthTokenType } from 'auth-cloud-lib'
import authClient from './authClient.js'

router.get('/:orgId/data',
  authClient.checkUserAuthentication(AuthTokenType.AccessToken),  // 1. who are you?
  authClient.checkUserAuthorization(createRule.entityOwner('orgId')),  // 2. are you allowed?
  handler,
)

createRule

Stateless factory functions — no need for the authClient instance.

createRule.entityOwner(attribute, location?, checkParents?)

Passes if the user owns the entity. Checks parent entities by default.

import { createRule, EntityIdLocation } from 'auth-cloud-lib'

createRule.entityOwner('orgId')
// → checks req.params.orgId, includes parents

createRule.entityOwner('orgId', EntityIdLocation.Query)
// → checks req.query.orgId

createRule.entityOwner('orgId', EntityIdLocation.Params, false)
// → checks req.params.orgId, no parent traversal

createRule.entityMember(attribute, location?, checkParents?)

Passes if the user is a member of the entity.

createRule.entityMember('orgId')
// → checks req.params.orgId

createRule.entityMember('orgId', EntityIdLocation.Body)
// → checks req.body.orgId

createRule.entityMember('orgId', EntityIdLocation.Body, false)
// → no parent traversal

createRule.entityPermission(permissions, attribute, location?, checkParents?)

Passes if the user has at least one of the required permissions on the entity.

createRule.entityPermission('org:manage', 'orgId')
// → user must have 'org:manage' on req.params.orgId

createRule.entityPermission(['org:read', 'org:write'], 'orgId')
// → user must have 'org:read' OR 'org:write'

createRule.entityPermission('data:write', 'orgId', EntityIdLocation.Body, false)
// → reads from req.body.orgId, no parent traversal

authClient.createRule.systemPermission(permissions)

Passes if the user has the required permission on the system entity (the global top-level entity). Requires systemEntityId to be set in the config.

authClient.createRule.systemPermission('apps:create')
authClient.createRule.systemPermission(['apps:read', 'apps:write'])

createPolicy

Composes multiple rules. Policies can be nested inside other policies.

createPolicy.or(rules) — default

Passes if any rule passes.

import { createRule, createPolicy } from 'auth-cloud-lib'

createPolicy.or([
  createRule.entityOwner('orgId'),
  createRule.entityMember('orgId'),
])

createPolicy.and(rules)

Passes only if all rules pass.

createPolicy.and([
  createRule.entityMember('orgId'),
  createRule.entityPermission('data:write', 'orgId'),
])

Nested policies

// Owner OR (member AND has write permission)
createPolicy.or([
  createRule.entityOwner('orgId'),
  createPolicy.and([
    createRule.entityMember('orgId'),
    createRule.entityPermission('data:write', 'orgId'),
  ]),
])

Complete route example

import express from 'express'
import { createRule, createPolicy, AuthTokenType } from 'auth-cloud-lib'
import authClient from './authClient.js'

const router = express.Router()

// Anyone authenticated can list
router.get('/:orgId/items',
  authClient.checkUserAuthentication(AuthTokenType.AccessToken),
  authClient.checkUserAuthorization(createPolicy.or([
    createRule.entityOwner('orgId'),
    createRule.entityMember('orgId'),
  ])),
  listItemsHandler,
)

// Only owners or users with write permission can create
router.post('/:orgId/items',
  authClient.checkUserAuthentication(AuthTokenType.AccessToken),
  authClient.checkUserAuthorization(createPolicy.or([
    createRule.entityOwner('orgId'),
    createRule.entityPermission('items:write', 'orgId'),
  ])),
  createItemHandler,
)

// System-level admin only
router.delete('/admin/nuke',
  authClient.checkUserAuthentication(AuthTokenType.AccessToken),
  authClient.checkUserAuthorization(authClient.createRule.systemPermission('admin:all')),
  nukeHandler,
)

EntityIdLocation

Controls where the entity ID is read from.

| Constant | Value | Source | |---|---|---| | EntityIdLocation.Params | params | req.params (default) | | EntityIdLocation.Query | query | req.query | | EntityIdLocation.Body | body | req.body (supports dot-notation: 'org.id') | | EntityIdLocation.Env | env | process.env (or envVars from config if provided) |

For EntityIdLocation.Env you do not need to pass anything: the library reads from process.env. Pass envVars in the config only if you want a different source (e.g. your validated env object from envalid).


TypeScript — req.user type

Importing anything from auth-cloud-lib automatically augments the Express Request type:

req.user            // { id: string, token: string, sessionId: string } | undefined
req.serviceAccount  // { id: string } | undefined

No additional setup is needed.


Build

npm run build   # compiles src/ → dist/
npm run dev     # watch mode