better-auth-abac
v1.3.1
Published
A package for ABAC in better-auth
Readme
IN BETA - IN DEVELOPMENT
better-auth-abac
A flexible and extensible Attribute-Based Access Control (ABAC) plugin for the Better Auth framework. This package allows developers to implement fine-grained authorization using attributes, policies, and rules with comprehensive access control validation.
Features
- Attribute-Based Access Control: Define and manage user, role, resource, action, and environment attributes
- Policy Management: Create flexible policy sets with priority-based evaluation
- Dynamic Attributes: Support for computed attributes with caching
- Resource Management: Comprehensive resource type and instance management
- Access Logging: Built-in access request tracking and audit trails
- Multiple Authorization Patterns: Support for read, write, delete, and custom action permissions
- Extensible Schema: Flexible attribute system supporting various data types and categories
Installation
npm install better-auth-abacSetup
import { betterAuth } from "better-auth"
import { abac, createAbacAdapter } from "better-auth-abac"
// Initialize your database adapter
const abacAdapter = await createAbacAdapter({
type: "mysql" // mysql | postgres | sqlite
uri: process.env.DB_URL!
// filename: "./db" // OPTIONAL FOR SQLITE
})
export const auth = betterAuth({
// other options here
plugins: [abac(abacAdapter)]
})Alternative Setup with Options
const abacAdapter = await createAbacAdapter({
type: "mysql" // mysql | postgres | sqlite
uri: process.env.DB_URL!
// filename: "./db" // OPTIONAL FOR SQLITE
})
const OPTIONS = {
database: drizzleAdapter(main_db, {
provider: "mysql",
schema: {
...schema,
},
}),
emailAndPassword: {
enabled: true,
},
plugins: [abac(abacAdapter)]
} satisfies BetterAuthOptions;
export const auth = betterAuth({
...OPTIONS,
appName: "My App"
})Database Schema
⚠️ IMPORTANT: Please remember to run
npx @better-auth/cli generateand push changes to your database before using this plugin.
The plugin automatically creates the following tables in your database:
- role: User roles with attributes
- attribute: Attribute definitions with types and categories
- user_attribute: User-specific attribute assignments
- role_attribute: Role-based attribute assignments
- resource_type: Definitions for different resource types
- resource: Resource instances with ownership
- resource_attribute: Resource-specific attributes
- actions: Available actions per resource type
- action_attribute: Action-specific attributes
- environment_attribute: Context-based attributes
- policy_set: Policy groupings with priorities
- policy: Individual policies with rules
- policy_rule: Detailed policy rule definitions
- policy_target: Policy targeting specifications
- access_request: Access request audit logs
- dynamic_attribute: Computed attributes with caching
Usage
Client-Side API
Check User Action Permissions
// Check if user can perform a specific action
const result = await authClient.abac.canuserperformaction({
subjectId: "user123",
resourceId: "document456", // optional
resourceType: "document", // optional
actionName: "edit",
context: {
ip_address: "192.168.1.1",
time_of_day: "business_hours",
department: "engineering",
},
});
console.log(result);
// EXAMPLE RETURN
{
"decision": {
"decision": "not_applicable", // not_applicable, permit, deny
"reason": "No applicable policies found", // reason for permit / deny / not_applic
"appliedPolicies": [], // applied policies to the decision
"processingTimeMs": 292
}
}Check Read Permissions
const canRead = await authClient.abac.canuserread({
userId: "user123",
resourceId: "document456",
context: {
classification_level: "internal",
},
});
console.log(canRead);Check Write Permissions
const canWrite = await authClient.abac.canuserwrite({
userId: "user123",
resourceId: "document456",
context: {
modification_reason: "content_update",
},
});
console.log(canWrite);Check Delete Permissions
const canDelete = await authClient.abac.canuserdelete({
userId: "user123",
resourceId: "document456",
context: {
backup_exists: "true",
},
});
console.log(canDelete);Bulk Resource Permission Check
// Check permissions across multiple resources
const bulkResult = await authClient.abac.canuserperformactiononresources({
userId: "user123",
actionName: "view",
resourceIds: ["doc1", "doc2", "doc3"],
context: {
request_purpose: "audit",
},
});
console.log(bulkResult);Test Plugin Connection
const testResult = await authClient.abac.test();
console.log(testResult.message); // "ABAC plugin is working!"Server-Side Integration
The plugin automatically handles user registration by:
- Creating a default "USER" role if it doesn't exist
- Assigning new users to the default role
- Creating user resources for access control
Policy Configuration
Policies are stored as JSON structures in the database and support:
- Attribute Matching: Compare user, resource, action, and environment attributes
- Logical Operators: AND, OR conditions between rules
- Comparison Operators: equals, not_equals, greater_than, less_than, contains, etc.
- Priority Handling: Higher priority policies override lower priority ones
- Effect Types: Allow or Deny decisions
Dynamic Attributes
Support for computed attributes that are:
- Calculated at runtime based on rules
- Cached for performance (configurable timeout)
- Context-aware and environment-sensitive
Environment Context
The plugin supports rich contextual information including:
- IP addresses and geographic location
- Time-based access (business hours, weekends)
- Device and browser information
- Custom application context
API Endpoints
All endpoints are automatically mounted under /api/auth/abac/:
POST /api/auth/abac/canuserperformaction- Generic action permission checkPOST /api/auth/abac/canuserread- Read permission checkPOST /api/auth/abac/canuserwrite- Write permission checkPOST /api/auth/abac/canuserdelete- Delete permission checkPOST /api/auth/abac/canuserperformactiononresources- Bulk permission checkGET /api/auth/abac/test- Plugin health check
Example Use Cases
Document Management System
// Check if user can edit a document based on:
// - User's role and department
// - Document classification level
// - Current time (business hours only)
// - User's previous edit history
const canEdit = await authClient.abac.canuserperformaction({
subjectId: userId,
resourceId: documentId,
resourceType: "document",
actionName: "edit",
context: {
current_time: new Date().toISOString(),
user_department: "legal",
document_classification: "confidential",
recent_edit_count: "2",
},
});Multi-tenant SaaS Application
// Ensure users can only access resources in their tenant
const canAccess = await authClient.abac.canuserperformactiononresources({
userId: userId,
actionName: "view",
resourceIds: requestedResourceIds,
context: {
tenant_id: userTenantId,
subscription_level: "premium",
feature_flags: JSON.stringify(enabledFeatures),
},
});Contributing
Contributions are welcome! Please ensure your code follows the established patterns and includes appropriate tests.
License
MIT License
