Skip to main content
Prisma Documentation Docs

Search documentation

Type to search this documentation.

On this pageOverview

Fine-Grained Authorization (Permit)

Prisma ORM does not include built-in authorization. This guide shows how to implement fine-grained authorization in your Prisma applications using the @permitio/permit-prisma extension.

Fine-grained authorization (FGA) controls which records a user can read or modify. Without it, your application might expose sensitive data or allow unauthorized modifications.

This extension supports three access control models from Permit.io:

What it is: Users are assigned roles (Admin, Editor, Viewer) with predefined permissions to perform actions on resource types.

Example: An "Editor" role can update any document in the system.

Best for: Simple permission structures where access is determined by job function or user level.

What it is: Access decisions based on attributes of users, resources, or environment.

Examples:

  • Allow access if user.department == document.department
  • Allow updates if document.status == "DRAFT"

How it works with the extension: When enableAttributeSync is on, resource attributes are automatically synced to Permit.io for policy evaluation.

Best for: Dynamic rules that depend on context or data properties.

What it is: Permissions based on relationships between users and specific resource instances.

Example: A user is an "Owner" of document-123 but just a "Viewer" of document-456.

How it works with the extension:

  • Resource instances are synced to Permit.io (with enableResourceSync: true)
  • Permission checks include the specific resource instance ID

Best for: Collaborative applications where users need different permissions on different instances of the same resource type.

  • RBAC: When you need simple, role-based access control
  • ABAC: When decisions depend on data properties or contextual information
  • ReBAC: When users need different permissions on different instances

Before implementing fine-grained authorization with Prisma, make sure you have:

  • A Prisma application with existing models and queries
  • Basic understanding of authorization concepts
  • Node.js and npm installed

Install the extension alongside Prisma Client:

bun add @permitio/permit-prisma @prisma/client@7
Bash
pnpm add @permitio/permit-prisma @prisma/client@7
Bash
yarn add @permitio/permit-prisma @prisma/client@7
Bash
npm install @permitio/permit-prisma @prisma/client@7

You'll also need to sign up for a Permit account to define your authorization policies.

Note:
Ensure that the Permit PDP container is running. It is recommended to run it using Docker for better performance, security, and availability. For instructions, refer to the Permit documentation: Deploy Permit to Production and PDP Overview.

You'll also need to sign up for a Permit account to define your authorization policies.

Note:
Ensure that the Permit PDP container is running. It is recommended to run it using Docker for better performance, security, and availability. For instructions, refer to the Permit documentation: Deploy Permit to Production and PDP Overview.

First, extend your Prisma Client with the Permit extension:

import { PrismaClient } from "@prisma/client";

import { createPermitClientExtension } from "@permitio/permit-prisma";

const prisma = new PrismaClient().$extends(

  createPermitClientExtension({

    permitConfig: {

      token: process.env.PERMIT_API_KEY, // Your Permit API key

      pdp: "http://localhost:7766", // PDP address (local or cloud)

    },

    enableAutomaticChecks: true, // Automatically enforce permissions

  }),

);

RBAC uses roles to determine access permissions. For example, "Admin" roles can perform all actions while "Viewer" roles can only read data.

  1. Define resources and actions in Permit.io dashboard:

    • Create resources matching your Prisma models (e.g., "document")
    • Define actions (e.g., "create", "read", "update", "delete")
    • Create roles with permission sets (e.g., "admin", "editor", "viewer")
  2. Set the active user in your code:

// Set the current user context before performing operations

prisma.$permit.setUser("john@example.com");

// All subsequent operations will be checked against this user's permissions

const documents = await prisma.document.findMany();

ABAC extends access control by considering user attributes, resource attributes, and context.

  1. Configure the extension for ABAC:
const prisma = new PrismaClient().$extends(

  createPermitClientExtension({

    permitConfig: { token: process.env.PERMIT_API_KEY, pdp: "http://localhost:7766" },

    enableAutomaticChecks: true,

  }),

);
  1. Set user with attributes:
prisma.$permit.setUser({

  key: "doctor@hospital.com",

  attributes: { department: "cardiology" },

});

// Will succeed only if user department matches record department (per policy)

const records = await prisma.medicalRecord.findMany({

  where: { department: "cardiology" },

});

ReBAC models permissions based on relationships between users and specific resource instances.

  1. Configure the extension for ReBAC:
const prisma = new PrismaClient().$extends(

  createPermitClientExtension({

    permitConfig: { token: process.env.PERMIT_API_KEY, pdp: "http://localhost:7766" },

    accessControlModel: "rebac",

    enableAutomaticChecks: true,

    enableResourceSync: true, // Sync resource instances with Permit.io

    enableDataFiltering: true, // Filter queries by permissions

  }),

);
  1. ** Access instance-specific resources:**
prisma.$permit.setUser("owner@example.com");

// Will only succeed if the user has permission on this specific file

const file = await prisma.file.findUnique({

  where: { id: "file-123" },

});

For more control, you can perform explicit permission checks:

// Check if user can update a document

const canUpdate = await prisma.$permit.check(

  "john@example.com", // user

  "update", // action

  "document", // resource

);

if (canUpdate) {

  await prisma.document.update({

    where: { id: "doc-123" },

    data: { title: "Updated Title" },

  });

}

// Or enforce permissions (throws if denied)

await prisma.$permit.enforceCheck("john@example.com", "delete", {

  type: "document",

  key: "doc-123",

});

Here are some common scenarios where fine-grained authorization is valuable:

  • Multi-tenant applications: Isolate data between different customers
  • Healthcare applications: Ensure patient data is only accessible to authorized staff
  • Collaborative platforms: Grant different permissions on shared resources
  • Content management systems: Control who can publish, edit, or view content

By integrating the @permitio/permit-prisma extension with your Prisma ORM application, you can implement authorization policies that protect your data and ensure users only access what they're permitted to see. The extension supports all major authorization models (RBAC, ABAC, ReBAC) and provides both automatic and manual permission enforcement.

Suggest an edit

Propose a replacement for this page. The site team reviews it before applying any changes.

Export
Documentation menu