# @casl/ability

> CASL is an isomorphic authorization JavaScript library which restricts what resources a given user is allowed to access

Latest version **7.0.1** (published 2026-07-06) · MIT license · 0 weekly downloads

## Install

```sh
npm install @casl/ability
pnpm add @casl/ability
yarn add @casl/ability
bun add @casl/ability
```

## Health

**Score 65/100 (B)** — status: active.

Positive: esm support; no vulnerabilities; has provenance; recently updated; high maintenance score.

Warnings: low downloads; no types.

## Facts

| | |
|---|---|
| Version | 7.0.1 |
| Published | 2026-07-06 |
| First published | 2018-02-22 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | none |
| Module format | ESM + CommonJS |
| Dependencies | 1 |
| Unpacked size | 178.4 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Provenance | attested (GitHub Actions) |
| GitHub stars | 7085 |
| Author | Sergii Stotskyi |
| Maintainers | stalniy |
| Keywords | permissions, authorization, acl, abac, rbac, ibac, cancan |

## Links

- npm: https://www.npmjs.com/package/@casl/ability
- Repository: https://github.com/stalniy/casl
- Homepage: https://casl.js.org
- Issues: https://github.com/stalniy/casl/issues
- Funding: https://github.com/stalniy/casl/blob/master/BACKERS.md
- npm.io page: https://npm.io/package/@casl/ability

## Dependencies (1)

- [@ucast/mongo2js](https://npm.io/package/@ucast/mongo2js.md) ^2.0.0

## Alternatives

- [@clerk/clerk-expo](https://npm.io/package/@clerk/clerk-expo.md) — 133.6K weekly downloads
- [@pothos/plugin-authz](https://npm.io/package/@pothos/plugin-authz.md) — 12.4K weekly downloads
- [@bounded-sh/client](https://npm.io/package/@bounded-sh/client.md) — 3.2K weekly downloads
- [@luigi-project/plugin-auth-oauth2](https://npm.io/package/@luigi-project/plugin-auth-oauth2.md) — 2.3K weekly downloads
- [@nocobase/plugin-verification](https://npm.io/package/@nocobase/plugin-verification.md) — 2.0K weekly downloads

## Recent versions

- 7.0.1 (latest) — 2026-07-06
- 7.0.0-rc (next) — 2026-05-08
- 2.0.0-alpha.ade5be4a (canary) — 2018-03-18
- 7.0.0 — 2026-05-21
- 6.8.1 — 2026-04-20
- 6.8.0 — 2026-01-18
- 6.7.5 — 2025-12-20
- 6.7.3 — 2025-01-05
- 6.7.2 — 2024-10-30
- 6.7.1 — 2024-03-27
- 6.7.0 — 2024-02-23
- 6.6.0 — 2024-02-23
- 6.5.0 — 2023-04-28
- 6.4.0 — 2023-04-02
- 6.3.4 — 2023-04-02
- … 77 more at https://npm.io/package/@casl/ability/versions

## README

# [CASL Ability](https://stalniy.github.io/casl/) [![@casl/ability NPM version](https://badge.fury.io/js/%40casl%2Fability.svg)](https://badge.fury.io/js/%40casl%2Fability)  [![](https://img.shields.io/npm/dm/%40casl%2Fability.svg)](https://www.npmjs.com/package/%40casl%2Fability) [![CASL Documentation](https://img.shields.io/badge/documentation-available-brightgreen.svg)](https://stalniy.github.io/casl/) [![Support](https://img.shields.io/badge/Support-github%20discussions-green?style=flat&link=https://github.com/stalniy/casl/discussions)](https://github.com/stalniy/casl/discussions)

This package is the core of CASL. It includes logic responsible for [checking and defining][intro] permissions.

## Installation

```sh
npm install @casl/ability
# or
pnpm install @casl/ability
# or
yarn add @casl/ability
```

## Documentation

This README file contains only basic information about the package. If you need an in depth introduction, please visit [CASL's documentation](https://casl.js.org/).

## Getting Started

**Note**: the best way to get started is to read the [Guide][intro] in the official documentation. In this README file, you will find just basic information.

**Note**: all the examples below are written in ES6 using ES modules but CASL also has a sophisticated support for TypeScript, read [CASL TypeScript support][typescript-support] for details.

### 1. Define Abilities

Lets define `Ability` for a blog website where visitors:
* can read blog posts
* can manage (i.e., do anything) own posts
* cannot delete a post if it was created more than a day ago

```js
import { AbilityBuilder, createMongoAbility } from '@casl/ability';
import { User } from '../models'; // application specific interfaces

/**
 * @param user contains details about logged in user: its id, name, email, etc
 */
function defineAbilitiesFor(user) {
  const { can, cannot, build } = new AbilityBuilder(createMongoAbility);

  // can read blog posts
  can('read', 'BlogPost');
  // can manage (i.e., do anything) own posts
  can('manage', 'BlogPost', { author: user.id });
  // cannot delete a post if it was created more than a day ago
  cannot('delete', 'BlogPost', {
    createdAt: { $lt: Date.now() - 24 * 60 * 60 * 1000 }
  });

  return build();
});
```

Do you see how easily business requirements were translated into CASL's rules?

And yes, `Ability` class allow you to use some MongoDB operators to define conditions. Don't worry if you don't know MongoDB, it's not required and explained in details in [Defining Abilities][define-abilities]

### 2. Check Abilities

Later on you can check abilities by using `can` and `cannot` methods of `Ability` instance.

```js
import { BlogPost, ForbiddenError } from '../models';

const user = getLoggedInUser(); // app specific function
const ability = defineAbilitiesFor(user)

// true if ability allows to read at least one Post
ability.can('read', 'BlogPost');

// true if there is no ability to read this particular blog post
const post = new BlogPost({ title: 'What is CASL?' });
ability.cannot('read', post);

// you can even throw an error if there is a missed ability
ForbiddenError.from(ability).throwUnlessCan('read', post);
```

Of course, you are not restricted to use only class instances in order to check permissions on objects. See [Introduction][intro] for the detailed explanation.

### 3. Database integration

CASL has a complementary package [@casl/mongoose] which provides easy integration with MongoDB and [mongoose].

```js
import { accessibleRecordsPlugin } from '@casl/mongoose';
import mongoose from 'mongoose';

mongoose.plugin(accessibleRecordsPlugin);

const user = getUserLoggedInUser(); // app specific function

const ability = defineAbilitiesFor(user);
const BlogPost = mongoose.model('BlogPost', mongoose.Schema({
  title: String,
  author: mongoose.Types.ObjectId,
  content: String,
  createdAt: Date,
  hidden: { type: Boolean, default: false }
}))

// returns mongoose Query, so you can chain it with other conditions
const posts = await Post.accessibleBy(ability).where({ hidden: false });

// you can also call it on existing query to enforce permissions
const hiddenPosts = await Post.find({ hidden: true }).accessibleBy(ability);

// you can even pass the action as a 2nd parameter. By default action is "read"
const updatablePosts = await Post.accessibleBy(ability, 'update');
```

See [Database integration][database-integration] for details.

### 4. Advanced usage

**CASL is incrementally adoptable**, that means you can start your project with simple claim (or action) based authorization and evolve it later, when your app functionality evolves.

**CASL is composable**, that means you can implement alternative conditions matching (e.g., based on [joi], [ajv] or pure functions) and field matching (e.g., to support alternative syntax in fields like `addresses.*.street` or `addresses[0].street`) logic.

See [Advanced usage][advanced-usage] for details.

[joi]: https://www.npmjs.com/package/@hapi/joi
[ajv]: https://www.npmjs.com/package/ajv

### 5. Performance and computational complexity

CASL checks are quite fast, thanks to underlying rule index structure. The estimated complexity of different operations can be found below:

| Operation                        | Complexity | Notes         |
|----------------------------------|------------|---------------|
| `Ability` creation time          | O(n)       | n - amount of rules |
| Check by action and subject type (e.g., `ability.can('read', 'Todo')`) | O(1) | |
| Check by action and subject object (e.g., `ability.can('read', todo)`) | O(m + k) + O(p) | m - amount of rules for the same pair of action and subject; k - amount of operators in conditions; O(p) - complexity of used operators (e.g., `$in` implementation is more complex than `$lt`) |

## Want to help?

Want to file a bug, contribute some code, or improve documentation? Excellent! Read up on guidelines for [contributing]

## License

[MIT License](http://www.opensource.org/licenses/MIT)

[contributing]: https://github.com/stalniy/casl/blob/master/CONTRIBUTING.md
[define-abilities]: https://stalniy.github.io/casl/en/guide/define-rules
[intro]: https://stalniy.github.io/casl/en/guide/intro
[database-integration]: https://stalniy.github.io/casl/en/package/casl-mongoose
[advanced-usage]: https://stalniy.github.io/casl/en/advanced/customize-ability
[typescript-support]: https://stalniy.github.io/casl/en/advanced/typescript

---
_Source: https://npm.io/package/@casl/ability · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
