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

@jcdubs/janus

v1.2.0

Published

Open source Serverless authentication: A Cedar-based authorisation engine for deterministic, deny-by-default access decisions through a CDK construct and SDK libraries.

Readme

Janus

CI License: MIT Node.js Version pnpm Dependabot

Open source serverless authentication: A Cedar-based authorization engine for deterministic, deny-by-default access decisions through a CDK construct and SDK libraries.

Overview

Janus is a TypeScript library that provides fine-grained, policy-based authorization for AWS Lambda functions using Cedar. It enables you to define complex authorization rules and evaluate them efficiently within your serverless applications.

Janus is based on the pattern discussed in this blog post: Serverless: Granular Authorisation with Cedar — High control, minimal cost.

Key Features

  • 🔐 Cedar Policy Engine - Leverage Amazon's Cedar policy language for authorization
  • Serverless Optimised - Designed for AWS Lambda with singleton caching
  • 🎯 Type-Safe - Full TypeScript support with comprehensive type definitions
  • 🔄 Fluent API - Intuitive method chaining for building authorization requests
  • 🧪 Well Tested - Comprehensive test coverage with real-world examples
  • 📦 Zero Config - Easy integration with minimal setup

Installation

Install the Package

npm install @jcdubs/janus

or

pnpm add @jcdubs/janus

or

yarn add @jcdubs/janus

Install Peer Dependencies

Janus requires the following peer dependencies to be installed in your project:

# For AWS Lambda PowerTools (logging)
npm install @aws-lambda-powertools/[email protected]

# For AWS CDK (if using CDK constructs)
npm install [email protected] [email protected]

With pnpm:

pnpm add @aws-lambda-powertools/[email protected]
pnpm add [email protected] [email protected]

With yarn:

yarn add @aws-lambda-powertools/[email protected]
yarn add [email protected] [email protected]

Note: The CDK dependencies (aws-cdk-lib and constructs) are only required if you're using Janus in a CDK application. For Lambda runtime usage only, you just need @aws-lambda-powertools/logger.

Quick Start

1. Define Your Cedar Policy

Create a policies.cedar file:

// Allow users to view their own orders
permit (
  principal,
  action == Action::"viewOrder",
  resource
) when {
  principal.id == resource.customerId
};

2. Define Your Cedar Schema

Create a schema.cedarschema file:

namespace OrderService {
  entity User = {
    id: String,
    roles: Set<Role>
  };
  
  entity Order = {
    customerId: String,
    status: String
  };
  
  entity Role;
  
  action viewOrder appliesTo {
    principal: User,
    resource: Order
  };
}

Implement the Auth Lambda

The following example demonstrates a simple AWS Lambda handler that uses the middleware to load Cedar authorization and then performs an authorization check inside the handler.

import middy from '@middy/core';
import type { APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda';
import {
  loadCedarAuthorization,
  AuthorizationService,
  EntityBuilder,
  getUserName,
} from '@jcdubs/janus';

const authorizationConfig = {
  namespace: 'OrderService::',
  principleType: 'User',
  resourceType: 'Order',
  roleType: 'Role',
};

const handler = async (
  event: APIGatewayProxyEvent,
): Promise<APIGatewayProxyResult> => {
  // AuthorizationService is cached by the middleware, but retrieving it here is safe
  // and inexpensive (cached) and makes the intent explicit in the handler.
  const authService = await AuthorizationService.getService(authorizationConfig);

  const resourceId = event.pathParameters?.orderId ?? 'order-123';

  const isAuthorized = authService
    .setAction('viewOrder')
    .setResource(resourceId)
    .addEntity(
      new EntityBuilder(resourceId, authorizationConfig)
        .withStringAttr('customerId', getUserName())
        .build(),
    )
    .isAuthorized();

  return {
    statusCode: isAuthorized ? 200 : 403,
    body: JSON.stringify({ allowed: isAuthorized }),
  };
};

export const main = middy(handler).use(loadCedarAuthorization(authorizationConfig));

3. Use the Authorization Service

import { AuthorizationService, EntityBuilder } from '@jcdubs/janus';

// Define the authorization configuration and initialize the service (cached as a singleton)
const authorizationConfig = {
  namespace: 'OrderService::',
  principleType: 'User',
  resourceType: 'Order',
  roleType: 'Role'
};

const authService = await AuthorizationService.getService(authorizationConfig);

// Examples showing varied `EntityBuilder` usage patterns

// Minimal: build an entity with only UID
const isAuthorizedMinimal = authService
  .setAction('viewOrder')
  .setResource('order-123')
  .addEntity(new EntityBuilder('order-123', authorizationConfig).build())
  .isAuthorized();

// Typical: add a few simple attributes
const isAuthorizedTypical = authService
  .setAction('viewOrder')
  .setResource('order-123')
  .addEntity(
    new EntityBuilder('order-123', authorizationConfig)
      .withStringAttr('customerId', 'user-456')
      .withStringAttr('status', 'PENDING')
      .withNumberAttr('items', 3)
      .build()
  )
  .isAuthorized();

// Full: include sets, references, extension attrs, parents and tags
const isAuthorizedFull = authService
  .setAction('viewOrder')
  .setResource('order-123')
  .addEntity(
    new EntityBuilder('order-123', authorizationConfig)
      .withStringAttr('customerId', 'user-456')
      .withBooleanAttr('active', true)
      .withNumberAttr('items', 5)
      .withSetAttr('flags', ['flagA', 'flagB'])
      .withAttr('owner', 'u1', authorizationConfig.principleType)
      .withExtnAttr('ip', 'ipaddr', '192.168.1.10')
      .withParent('role-1', 'Role')
      .withTag('label', 'lbl1', 'Label')
      .build()
  )
  .isAuthorized();

logger.info('Create authorisation requests', isAuthorizedMinimal, isAuthorizedTypical, isAuthorizedFull);

API Reference

AuthorizationService

Static Methods

getService(config, refresh?)

Retrieves or creates a cached instance of the Authorization Service.

Parameters:

  • config: AuthorizationConfigType - Configuration object
    • namespace: string - Cedar namespace (e.g., 'OrderService::')
    • principleType: string - Principal entity type (e.g., 'User')
    • resourceType: string - Resource entity type (e.g., 'Order')
    • roleType: string - Role entity type (e.g., 'Role')
  • refresh?: boolean - Force reload policies and schemas (default: false)

Returns: Promise<AuthorizationService>

Instance Methods

setAction(action)

Sets the action to be authorized.

Parameters:

  • action: string - The action name

Returns: this (for chaining)

setResource(resource)

Sets the resource identifier.

Parameters:

  • resource: string - The resource ID

Returns: this (for chaining)

setContext(context)

Sets the authorization context.

Parameters:

  • context: Record<string, cedar.CedarValueJson> - Context data

Returns: this (for chaining)

addEntity(entity)

Adds an entity to the authorization request.

Parameters:

  • entity: cedar.EntityJson - Entity definition

Returns: this (for chaining)

addEntities(entities)

Adds multiple entities to the authorization request.

Parameters:

  • entities: cedar.EntityJson[] - Array of entity definitions

Returns: this (for chaining)

isAuthorized()

Evaluates the authorization request.

Returns: boolean - true if authorized, false otherwise

Throws:

  • MissingAuthenticatedUserDetailsError - If user details are missing
  • MissingAuthorizationActionError - If action is not set
  • MissingAuthorizationResourceError - If resource is not set
  • MissingAuthorizationPolicyError - If policies cannot be loaded
  • MissingAuthorizationSchemaError - If schema cannot be loaded

Middleware

authorizationMiddleware

Middy middleware for automatic authorization in Lambda handlers.

import { authorizationMiddleware } from '@jcdubs/janus';
import middy from '@middy/core';

const handler = middy(async (event) => {
  // Your handler logic
})
  .use(authorizationMiddleware({
    namespace: 'OrderService::',
    principleType: 'User',
    resourceType: 'Order',
    roleType: 'Role',
  }));

Auth Lambda Construct

Provides a CDK construct to bundle a Node.js Lambda with Cedar policy and schema files and the Cedar WASM runtime.

  • Export: AuthLambda (class)
  • Props: AuthLambdaProps — extends NodejsFunctionProps and adds authorisation: { policyFilePath: string; schemaFilePath: string }.

Usage: Use AuthLambda in CDK stacks to ensure Cedar policies and schema are bundled with the Lambda package and the Cedar WASM runtime copied into node_modules/@cedar-policy/cedar-wasm. In particular, AuthLambda makes sure the @cedar-policy/cedar-wasm package, your Cedar policy file (for example policies.cedar) and your Cedar schema file (for example schema.cedarschema) are included in the Lambda deployment package so they are available at runtime.

EntityBuilder

Fluent builder for creating Cedar entity JSON objects used in authorization requests.

  • Export: EntityBuilder (class)
  • Constructor: new EntityBuilder(id: string, authorizationConfig: AuthorizationConfigType, type?: string)
  • Common Methods: withAttr(name, id, type), withExtnAttr(name, fn, arg), withBooleanAttr(name, value), withNumberAttr(name, value), withStringAttr(name, value), withSetAttr(name, value), withParent(id, type), withTag(name, id, type), build() — returns EntityJson.

Example usage is shown in the Quick Start section above.

File Loader

Small utility to read bundled files (Cedar policy and schema) from the Lambda package.

  • Export: loadFileAsString(fileName: string): string

Throws an Error if the file cannot be read. Typically used by the AuthorizationService to load policies.cedar and schema.cedarschema.

Types

Shared TypeScript types used across the library.

  • TypeAndId{ type: string; id: string }
  • EntityUidJson{ __entity: TypeAndId } | TypeAndId
  • CedarValueJson — union of entity refs, extn values, primitives, arrays, objects, or null
  • FnAndArg{ fn: string; arg: CedarValueJson }
  • EntityJson{ uid: EntityUidJson; attrs: Record<string, CedarValueJson>; parents: EntityUidJson[]; tags?: Record<string, CedarValueJson> }

Errors

The library exports a set of specific error classes used by the authorization flow.

  • MissingAuthenticatedUserDetailsError
  • MissingAuthorizationActionError
  • MissingAuthorizationPolicyError
  • MissingAuthorizationResourceError
  • MissingAuthorizationSchemaError
  • UnauthorizedError

These are exported from the errors module and are thrown by the AuthorizationService and middleware where applicable.

User Details

The library provides utilities to extract user information from Lambda events:

import { getUserName, getRoles } from '@jcdubs/janus';

const username = getUserName(event);
const roles = getRoles(event);

Error Handling

The library provides specific error classes for different authorization failures:

  • MissingAuthenticatedUserDetailsError
  • MissingAuthorizationActionError
  • MissingAuthorizationPolicyError
  • MissingAuthorizationResourceError
  • MissingAuthorizationSchemaError
  • UnauthorizedError

Examples

Order Service Example

The examples/order-service project demonstrates a complete integration of Janus in a real-world serverless service. It shows how the Janus CDK construct, middleware and SDK are used together to provide Cedar-based authorization for AWS Lambda CRUD handlers.

  • Janus Integration: The example uses the provided Auth Lambda construct and the authorizationMiddleware to bundle and load Cedar policy and schema files. The authorization checks inside the order CRUD Lambdas use the AuthorizationService from the Janus SDK (via the auth secondary adapter) to evaluate requests against the deployed Cedar policies and schema.
  • Full CRUD API: The example implements a full Create/Read/Update/Delete API for orders backed by the included lambda handlers.
  • Scripts: See the examples/order-service/scripts directory — it contains scripts to hydrate the database, create users and groups in the Cognito user pool, and login scripts for individual users associated with specific groups.
  • Postman Collection: A Postman collection (Auth.postman_collection.json) is included in the example. It contains requests that exercise each user and group against the Cedar policy and schema files deployed with the order CRUD Lambdas.

See the authorization-tests directory for comprehensive examples including:

  • Customer role permissions
  • Sales staff authorization
  • Manager access controls
  • Account manager restrictions
  • Accountant read-only access

Cedar Resources

Development

Prerequisites

  • Node.js 20+
  • pnpm 10+

Peer Dependencies

This project uses peer dependencies to avoid version conflicts. The required peer dependencies are:

Setup

# Install dependencies
pnpm install

# Run tests
pnpm test

# Run tests with coverage
pnpm test:coverage

# Build
pnpm build

Testing

# Run all tests
pnpm test

# Run tests in watch mode
pnpm test:watch

# Generate coverage report
pnpm test:coverage

Contributing

We welcome contributions! Please see CONTRIBUTING.md for details on how to get started.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Security

For security concerns, please see SECURITY.md.

Support

Acknowledgments