Skip to content

A lightweight and flexible authorization module for Nuxt App

License

Notifications You must be signed in to change notification settings

AwaludinAR/nuxt-authorizer

Repository files navigation

Nuxt Authorizer

npm version npm downloads License Nuxt pkg.pr.new

A lightweight and flexible authorization module for Nuxt App.

Features

  •  Declarative abilities - Define permission rules using a clean, composable API.
  •  Full-stack authorization - Works in both client and server through unified utilities.
  •  Component-level access control - <Can> and <Cannot> components included.
  •  Type-safe rules — Strong TypeScript support for better DX.
  •  Nested and array-based abilities - Model complex permission logic easily.
  •  Customizable callbacks & error handling - Override messages, status codes, and execution logic.

Quick Setup

Install the module to your Nuxt application with one command:

npx nuxi module add nuxt-authorizer

That's it! You can now use Nuxt Authorizer in your Nuxt app ✨

Documentation

Quick Start

Define ability

const editPost = defineAbility((user: User, post: Post) => user.id === post.authorId)

Usage (Client or Server)

const allowed = await allows(editPost, user, post)
const denied = await denies(editPost, user, post)

Usage with component

<template>
  <div>
    <Can :ability="editPost" :args="[user, post]">
      <p>Authorized</>
    </Can>
    <Cannot :ability="editPost" :args=[user, post]>
      <p>Unauthorized</>
    </Cannot>
  </div>
</template>

Usage with composables

<script lang="ts" setup>
const { authorized, execute } = useAbility(editPost)
</script>

<template>
  <div>
    <button @click="execute(user, post)">Edit</button>
    <div v-if="authorized">
      Authorized
    </div>
  </div>
</template>

Throw error if Unauthorized (Server)

await authorize(editPost, user, post)

Ability

Transform any function that has a boolean return, rule, or array rules into an ability.

Nested Ability

define ability

Note

You can define abilities wherever you want, but if static is recommended in the /shared/utils folder (Nuxt v4).

const ability = defineAbility((user: User) => {
  post: (post: Post) => ({
    edit: () => user.id === post.authorId,
    delete: () => user.role === 'admin' || user.id === post.authorId
  }),
  comment: () => ({
    create: () => !!user,
    edit: (comment: Comment) => user.id === comment.authorId
  })
})
Usage
// Server or Client
const allowed = await allows(ability, user, 'post', 'edit')
const denied = await denies(ability, user, 'post', 'edit')

// Server
await authorize(ability, user, 'post', 'edit')

// Composables
const {authorized, execute} = useAbility(ability)
execute(user, 'post', 'edit')
Usage with component
<template>
  <div>
    <Can :ability="ability" :args="[user, 'post', 'edit']">
      <div> Authorized </>
    </Can>
    <Cannot :ability="ability" :args="[user, 'post', 'edit']">
      <div> Authorized </>
    </Cannot>
  </div>
</template>

Array Abilities

Unlike nested abilities, Array abilities evaluate all rules. If any rule returns false, the result is false.

// define ability/rule
const editPost = defineAbility((user: User, post: Post) => user.id === post.authorId)
const arrayAbilities = defineAbility([
  editPost,
  () => true,
  async(user: User, post: Post) => Promise.resolve(user.id === post.authorId)
] as const /* for better type */)

// usage
const passed = await allows(arrayAbilities, [user, post /* ARGS_RULE_1 */], [/* ARGS_RULE_2 */], [/* ARGS_RULE_3 */])

// Composables
const {authorized, execute} = useAbility(arrayAbilities)
execute([user, post /* ARGS_RULE_1 */], [/* ARGS_RULE_2 */], [/* ARGS_RULE_3 */])
Use with component
<template>
  <div>
    <Can :ability="arrayAbilities" :args="[]">
  </div>
</template>

Nested Array Abilities

const canAccess = defineAbility([
  (user: User) => [
    async() => await isVerified(user.id),
    (role: string) => user.role === role, 
  ]
])

Dynamic rule

const rule = await getRuleByUser(userId)

const ability = defineAbility(rule)

// Usage
const allowed = await ability(/* PARAMETERS /*)

or you can use useAbility, composables accept functions (rules) or abilities

Components

Can Component will make content inside <slot/> visible if authorized is true.

Can Component

<template>
  <Can ability="..." args="[...]">
    <div>Visible if authorized true</div>
  </Can>
</template>

Cannot Component

Cannot Component will make content inside <slot/> visible if authorized is false.

<template>
  <Cannot ability="..." args="[...]">
    <div>Visible if authorized false</div>
  </Cannot>
</template>

Authorizer Component

with Authorizer Component lets you control both Can and Cannot components, and includes onAuthorized and onUnauthorized callbacks.

<template>
  <Authorizer ability="..." args"[...]" onAuthorized="..." onUnauthorized="...">
    <template #can>
      <div>Visible if Authorized is true</div>
    </template>

    <template #cannot>
      <div>Visible if Unauthorized is false</div>
    </template>
  </Authorizer>
</template>

Options

Set Callback in ability

const ability = defineAbility(() => true, {
  onAuthorized: () => {
    // Your implementations
  },
  onUnauthorized: (message, statusCode) => {
    // Your implementations
  }
})

Custom error status code and message

const ability = defineAbility(() => true, {
  statusCode: 401,
  message: 'Unauthorized'
})

Set Callback in composables

<script lang="ts" setup>

const { authorized } = useAbility(ability, {
  onAuthorized: () => {
    // Your implementations
  },
  onUnauthorized: (message, statusCode) => {
    // Your implementations
  }
})

</script>

Custom executor

const ability = defineAbility(() => true, {
  executor: (rule, args) => {
    return true
  }
})

Contribution

Local development
# Install dependencies
pnpm install

# Generate type stubs
pnpm run dev:prepare

# Develop with the playground
pnpm run dev

# Build the playground
pnpm run dev:build

# Run ESLint
pnpm run lint

# Run Vitest
pnpm run test
pnpm run test:watch

# Release new version
pnpm run release

About

A lightweight and flexible authorization module for Nuxt App

Resources

License

Stars

Watchers

Forks

Packages

No packages published