New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

@gentleduck/iam

Package Overview
Dependencies
Maintainers
1
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@gentleduck/iam

Modern ABAC/RBAC access control engine. Framework-agnostic core with integrations for Express, NestJS, Hono, Next.js, React, and Vue.

latest
Source
npmnpm
Version
1.6.1
Version published
Maintainers
1
Created
Source

@gentleduck/iam

Type-safe authorization engine for TypeScript. RBAC + ABAC with a policy engine, condition evaluation, scoped roles, and integrations for Express, NestJS, Hono, Next.js, React, Vue, and vanilla JS.

Zero runtime dependencies. Tree-shakeable. 23 KB full, under 1 KB per module.

Install

npm install @gentleduck/iam
# or
bun add @gentleduck/iam

Quick start

import { createAccessConfig } from '@gentleduck/iam'
import { MemoryAdapter } from '@gentleduck/iam/adapters/memory'

const access = createAccessConfig({
  actions: ['create', 'read', 'update', 'delete'] as const,
  resources: ['post', 'comment', 'user'] as const,
  roles: ['viewer', 'editor', 'admin'] as const,
})

const viewer = access.defineRole('viewer').grant('read', 'post').grant('read', 'comment').build()
const editor = access.defineRole('editor').inherits('viewer').grant('update', 'post').build()
const admin = access.defineRole('admin').inherits('editor').grantCRUD('post').grantCRUD('comment').build()

const policy = access
  .policy('blog')
  .rule('owner-edit', (r) => r.allow().on('update').of('post').when((w) => w.isOwner()))
  .build()

const adapter = new MemoryAdapter({
  policies: [policy],
  roles: [viewer, editor, admin],
  assignments: { 'user-1': ['editor'] },
})

const engine = access.createEngine({ adapter })
const allowed = await engine.can('user-1', 'read', { type: 'post', attributes: {} })
// true

Performance

Benchmarked against 7 JS authorization libraries using vitest bench. Simple RBAC check, ops/sec (higher is better):

Libraryops/secvs CASL
@casl/ability16,857,000baseline
@gentleduck/iam [PROD]8,233,0002x slower
easy-rbac5,003,0003.4x slower
@rbac/rbac2,884,0005.8x slower
accesscontrol674,00025x slower
casbin143,000118x slower
role-acl140,000120x slower

CASL is faster on raw lookups because it pre-compiles rules into a hash table at build time. duck-iam supports dynamic policies that can change at runtime, which costs an extra Map lookup per check.

For the smallest bundle, import only the evaluator:

import { evaluatePolicyFast } from '@gentleduck/iam'
const allowed = evaluatePolicyFast(policy, request) // boolean

Features

  • RBAC + ABAC combined in one engine
  • Policy engine with 4 combining algorithms (deny-overrides, allow-overrides, first-match, highest-priority)
  • 18 condition operators (eq, neq, gt, lt, in, contains, starts_with, matches, exists, subset_of, and more)
  • Scoped roles for multi-tenant systems
  • Dev/prod mode: rich Decision objects in development, plain booleans in production
  • Explain API: full evaluation trace showing exactly why a permission was granted or denied
  • Lifecycle hooks: beforeEvaluate, afterEvaluate, onDeny, onError
  • LRU caching with configurable TTL
  • Rule indexing with pre-computed results for unconditional rules
  • Type-safe config: actions, resources, roles, and scopes are validated at compile time

Integrations

Server middleware

// Express
import { guard } from '@gentleduck/iam/server/express'
app.delete('/posts/:id', guard(engine, 'delete', 'post'), handler)

// Hono
import { guard } from '@gentleduck/iam/server/hono'
app.delete('/posts/:id', guard(engine, 'delete', 'post'), handler)

// NestJS
import { nestAccessGuard, Authorize } from '@gentleduck/iam/server/nest'
@Authorize({ action: 'delete', resource: 'post' })

// Next.js
import { withAccess } from '@gentleduck/iam/server/next'
export const DELETE = withAccess(engine, 'delete', 'post', handler)

Client libraries

// React
import { createAccessControl } from '@gentleduck/iam/client/react'
const { AccessProvider, useAccess, Can, Cannot } = createAccessControl(React)

// Vue
import { createVueAccess } from '@gentleduck/iam/client/vue'
const { useAccess, Can, Cannot } = createVueAccess(vue)

// Vanilla JS
import { AccessClient } from '@gentleduck/iam/client/vanilla'
const client = await AccessClient.fromServer('/api/permissions')
client.can('read', 'post') // boolean

Database adapters

import { MemoryAdapter } from '@gentleduck/iam/adapters/memory'
import { PrismaAdapter } from '@gentleduck/iam/adapters/prisma'
import { DrizzleAdapter } from '@gentleduck/iam/adapters/drizzle'
import { HttpAdapter } from '@gentleduck/iam/adapters/http'

Module sizes (gzipped)

ModuleSize
Core (full)23.3 KB
Each adapter0.9 - 1.7 KB
Each server middleware0.8 - 1.3 KB
Each client library1.0 - 1.4 KB

Documentation

Full docs, course, and API reference: duck-iam docs

License

MIT

Keywords

rbac

FAQs

Package last updated on 02 Apr 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts