@devcraft-ts/abac-admin-nextjs
v1.0.4
Published
Next.js utilities for ABAC Policy Administration
Downloads
507
Maintainers
Readme
@devcraft-ts/abac-admin-nextjs
Next.js utilities for ABAC Policy Administration - Server-side API routes and React hooks
🚀 Live Demo & Documentation
Explore a fully functional Next.js demo application showcasing all features, including complete documentation for abac-engine integration and best practices.
Overview
@devcraft-ts/abac-admin-nextjs provides everything you need to build a complete ABAC policy administration interface in Next.js. It combines server-side API route helpers with client-side React hooks for a seamless full-stack experience.
Features
✅ Pre-built API Route Handlers - Drop-in route handlers for policies, attributes, and audit logs
✅ Authentication Middleware - Flexible middleware system with RBAC support
✅ Type-Safe - Full TypeScript support throughout
✅ Next.js App Router Ready - Built for Next.js 13+ App Router
✅ Automatic Validation - Built-in Zod validation for all endpoints
✅ React Hooks Included - Re-exports all hooks from @devcraft-ts/abac-admin-react
✅ Zero Config - Works out of the box with sensible defaults
✅ Built on abac-engine - Leverages the official abac-engine for policy evaluation
Installation
npm install @devcraft-ts/abac-admin-nextjs @devcraft-ts/abac-admin-core @devcraft-ts/abac-admin-react zodyarn add @devcraft-ts/abac-admin-nextjs @devcraft-ts/abac-admin-core @devcraft-ts/abac-admin-react zodpnpm add @devcraft-ts/abac-admin-nextjs @devcraft-ts/abac-admin-core @devcraft-ts/abac-admin-react zodQuick Start
1. Create API Routes
Policy Routes
// app/api/abac/policies/route.ts
import { createPolicyRoutes } from "@devcraft-ts/abac-admin-nextjs/server";
import { ABACAdminClient } from "@devcraft-ts/abac-admin-core";
const getClient = () =>
new ABACAdminClient({
baseURL: process.env.ABAC_API_URL!,
headers: {
Authorization: `Bearer ${process.env.ABAC_API_TOKEN}`,
},
});
export const { GET, POST } = createPolicyRoutes(getClient);// app/api/abac/policies/[id]/route.ts
import { createPolicyRoutes } from "@devcraft-ts/abac-admin-nextjs/server";
export const { PUT, DELETE } = createPolicyRoutes(getClient);Attribute Routes
// app/api/abac/attributes/[resourceType]/[resourceId]/route.ts
import { createAttributeRoutes } from "@devcraft-ts/abac-admin-nextjs/server";
export const { GET, POST } = createAttributeRoutes(getClient);Audit Routes
// app/api/abac/audit/route.ts
import { createAuditRoutes } from "@devcraft-ts/abac-admin-nextjs/server";
export const { GET } = createAuditRoutes(getClient);2. Use Hooks in Your Components
// app/admin/policies/page.tsx
"use client";
import { ABACProvider, usePolicies } from "@devcraft-ts/abac-admin-nextjs";
function PolicyList() {
const { policies, isLoading, createPolicy, deletePolicy } = usePolicies();
if (isLoading) return <div>Loading...</div>;
return (
<div>
{policies.map((policy) => (
<div key={policy.id}>
<h3>{policy.policyId}</h3>
<button onClick={() => deletePolicy(policy.id)}>Delete</button>
</div>
))}
</div>
);
}
export default function PoliciesPage() {
return (
<ABACProvider config={{ baseURL: "/api/abac" }}>
<PolicyList />
</ABACProvider>
);
}API Reference
Server-Side Utilities
All server utilities are imported from @devcraft-ts/abac-admin-nextjs/server:
import {
createPolicyRoutes,
createAttributeRoutes,
createAuditRoutes,
createAuthMiddleware,
} from "@devcraft-ts/abac-admin-nextjs/server";createPolicyRoutes
Creates Next.js route handlers for policy management.
const getClient = () =>
new ABACAdminClient({
baseURL: process.env.ABAC_API_URL!,
});
export const { GET, POST, PUT, DELETE, PATCH } = createPolicyRoutes(getClient);Endpoints Created:
GET /api/policies- List all policies with optional filtersGET /api/policies?isActive=true&category=document- Filtered listPOST /api/policies- Create a new policyPUT /api/policies/[id]- Update a policyDELETE /api/policies/[id]- Delete a policyPATCH /api/policies/[id]/activate- Activate a policyPATCH /api/policies/[id]/deactivate- Deactivate a policy
Request/Response Examples:
// POST /api/policies
{
"policyId": "doc-read-policy",
"version": "1.0.0",
"effect": "PERMIT",
"description": "Allow document reading",
"conditions": {
"type": "equals",
"left": { "category": "subject", "key": "role" },
"right": "admin"
},
"isActive": true,
"category": "document",
"tags": ["document", "read"],
"createdBy": "user-123"
}createAttributeRoutes
Creates Next.js route handlers for attribute management.
export const { GET, POST, DELETE } = createAttributeRoutes(getClient);Endpoints Created:
GET /api/attributes/[resourceType]/[resourceId]- Get all attributesGET /api/attributes/[resourceType]/[resourceId]?key=role- Get single attributePOST /api/attributes/[resourceType]/[resourceId]- Set attribute(s)DELETE /api/attributes/[resourceType]/[resourceId]/[key]- Delete attribute
Request Examples:
// POST /api/attributes/user/user-123
// Single attribute
{ "key": "role", "value": "admin" }
// Bulk attributes
{ "attributes": { "role": "admin", "level": 5, "department": "engineering" } }createAuditRoutes
Creates Next.js route handlers for audit log access.
export const { GET } = createAuditRoutes(getClient);Endpoints Created:
GET /api/audit- Get audit logsGET /api/audit?entityType=policy&action=UPDATE&limit=50- Filtered logs
createAuthMiddleware
Creates authentication middleware for protecting routes.
import { createAuthMiddleware } from "@devcraft-ts/abac-admin-nextjs/server";
import { cookies } from "next/headers";
const authMiddleware = createAuthMiddleware({
getAuthContext: async (request) => {
const token = cookies().get("session")?.value;
if (!token) return null;
const session = await verifyToken(token);
return {
userId: session.userId,
roles: session.roles,
permissions: session.permissions,
};
},
authorize: async (context, request) => {
// Check if user has admin role
return context.roles?.includes("admin") ?? false;
},
});
// Use in route handlers
export const GET = authMiddleware(async (request, context) => {
// context.userId is available here
return Response.json({ userId: context.userId });
});Configuration Options:
interface MiddlewareConfig {
getAuthContext: (request: NextRequest) => Promise<AuthContext | null>;
authorize?: (context: AuthContext, request: NextRequest) => Promise<boolean>;
onUnauthorized?: (request: NextRequest) => NextResponse;
onForbidden?: (context: AuthContext, request: NextRequest) => NextResponse;
onRequest?: (context: AuthContext | null, request: NextRequest) => void;
}Authorization Helpers
import {
requireRoles,
requirePermissions,
combineAuthAnd,
combineAuthOr,
createRequestLogger,
createRateLimiter,
} from "@devcraft-ts/abac-admin-nextjs/server";
// Require specific roles
const authMiddleware = createAuthMiddleware({
getAuthContext: async (request) => {
/* ... */
},
authorize: requireRoles(["admin", "manager"]),
});
// Require specific permissions
const authMiddleware = createAuthMiddleware({
getAuthContext: async (request) => {
/* ... */
},
authorize: requirePermissions(["policies:read", "policies:write"]),
});
// Combine multiple requirements (AND)
const authMiddleware = createAuthMiddleware({
getAuthContext: async (request) => {
/* ... */
},
authorize: combineAuthAnd([
requireRoles(["admin"]),
requirePermissions(["policies:write"]),
]),
});
// Combine multiple requirements (OR)
const authMiddleware = createAuthMiddleware({
getAuthContext: async (request) => {
/* ... */
},
authorize: combineAuthOr([
requireRoles(["admin"]),
requireRoles(["manager"]),
]),
});
// Add request logging
const authMiddleware = createAuthMiddleware({
getAuthContext: async (request) => {
/* ... */
},
onRequest: createRequestLogger(false), // true to include body
});
// Add rate limiting (simple in-memory)
const authMiddleware = createAuthMiddleware({
getAuthContext: async (request) => {
/* ... */
},
authorize: createRateLimiter(100, 60000), // 100 requests per minute
});Client-Side Hooks
All React hooks are re-exported from @devcraft-ts/abac-admin-react. Import them from @devcraft-ts/abac-admin-nextjs:
import {
ABACProvider,
usePolicies,
usePolicy,
useAttributes,
useAuditLog,
} from "@devcraft-ts/abac-admin-nextjs";For complete hook documentation, see @devcraft-ts/abac-admin-react README.
Complete Example
File Structure
app/
├── api/
│ └── abac/
│ ├── policies/
│ │ ├── route.ts # GET, POST /api/abac/policies
│ │ └── [id]/
│ │ ├── route.ts # PUT, DELETE /api/abac/policies/[id]
│ │ └── [action]/
│ │ └── route.ts # PATCH /api/abac/policies/[id]/activate
│ ├── attributes/
│ │ └── [resourceType]/
│ │ └── [resourceId]/
│ │ ├── route.ts # GET, POST
│ │ └── [key]/
│ │ └── route.ts # DELETE
│ └── audit/
│ └── route.ts # GET /api/abac/audit
├── admin/
│ ├── policies/
│ │ ├── page.tsx # Policy list page
│ │ └── [id]/
│ │ └── page.tsx # Policy detail page
│ └── layout.tsx # Admin layout with ABACProvider
└── lib/
├── abac-client.ts # ABAC client setup
└── auth-middleware.ts # Auth middleware configlib/abac-client.ts
import { ABACAdminClient } from "@devcraft-ts/abac-admin-core";
export function getABACClient() {
return new ABACAdminClient({
baseURL: process.env.ABAC_API_URL!,
headers: {
Authorization: `Bearer ${process.env.ABAC_API_TOKEN}`,
},
});
}lib/auth-middleware.ts
import {
createAuthMiddleware,
requireRoles,
} from "@devcraft-ts/abac-admin-nextjs/server";
import { cookies } from "next/headers";
export const authMiddleware = createAuthMiddleware({
getAuthContext: async (request) => {
const session = cookies().get("session")?.value;
if (!session) return null;
// Verify session and return user context
const user = await verifySession(session);
return {
userId: user.id,
roles: user.roles,
permissions: user.permissions,
};
},
authorize: requireRoles(["admin", "policy-manager"]),
});app/api/abac/policies/route.ts
import { createPolicyRoutes } from '@devcraft-ts/abac-admin-nextjs/server';
import { getABACClient } from '@/lib/abac-client';
import { authMiddleware } from '@/lib/auth-middleware';
const { GET, POST } = createPolicyRoutes(getABACClient);
// Protect routes with authentication
export { GET: authMiddleware(GET), POST: authMiddleware(POST) };app/admin/layout.tsx
"use client";
import { ABACProvider } from "@devcraft-ts/abac-admin-nextjs";
export default function AdminLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<ABACProvider config={{ baseURL: "/api/abac" }}>
<div className="admin-layout">
<nav>{/* Navigation */}</nav>
<main>{children}</main>
</div>
</ABACProvider>
);
}app/admin/policies/page.tsx
"use client";
import { usePolicies } from "@devcraft-ts/abac-admin-nextjs";
export default function PoliciesPage() {
const {
policies,
isLoading,
error,
createPolicy,
deletePolicy,
activatePolicy,
} = usePolicies();
if (isLoading) return <div>Loading policies...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<div>
<h1>Policies ({policies.length})</h1>
<div className="policy-list">
{policies.map((policy) => (
<div key={policy.id} className="policy-card">
<h3>{policy.policyId}</h3>
<p>{policy.description}</p>
<div className="actions">
<button onClick={() => activatePolicy(policy.id)}>
Activate
</button>
<button onClick={() => deletePolicy(policy.id)}>Delete</button>
</div>
</div>
))}
</div>
</div>
);
}Advanced Usage
Dynamic Authentication
// app/api/abac/policies/route.ts
import { cookies } from "next/headers";
const getClient = () => {
const token = cookies().get("auth-token")?.value;
return new ABACAdminClient({
baseURL: process.env.ABAC_API_URL!,
headers: token
? {
Authorization: `Bearer ${token}`,
}
: {},
});
};
export const { GET, POST } = createPolicyRoutes(getClient);Custom Error Responses
const authMiddleware = createAuthMiddleware({
getAuthContext: async (request) => {
/* ... */
},
onUnauthorized: (request) => {
return NextResponse.json(
{ error: "Please log in to access this resource" },
{ status: 401 },
);
},
onForbidden: (context, request) => {
return NextResponse.json(
{ error: `User ${context.userId} does not have permission` },
{ status: 403 },
);
},
});Request Logging
const authMiddleware = createAuthMiddleware({
getAuthContext: async (request) => {
/* ... */
},
onRequest: (context, request) => {
console.log({
timestamp: new Date().toISOString(),
userId: context?.userId ?? "anonymous",
method: request.method,
url: request.url,
});
},
});Multiple Client Configurations
// Different clients for different routes
const adminClient = () =>
new ABACAdminClient({
baseURL: process.env.ADMIN_API_URL!,
headers: { "X-Role": "admin" },
});
const userClient = () =>
new ABACAdminClient({
baseURL: process.env.USER_API_URL!,
headers: { "X-Role": "user" },
});
// app/api/admin/policies/route.ts
export const { GET, POST } = createPolicyRoutes(adminClient);
// app/api/user/policies/route.ts
export const { GET } = createPolicyRoutes(userClient);TypeScript Support
Full TypeScript support with comprehensive type definitions:
import type {
PolicyRouteHandlers,
AttributeRouteHandlers,
AuditRouteHandlers,
AuthContext,
MiddlewareConfig,
UsePoliciesResult,
Policy,
PolicyInput,
} from "@devcraft-ts/abac-admin-nextjs";Best Practices
1. Use Environment Variables
ABAC_API_URL=https://api.example.com/abac
ABAC_API_TOKEN=your-secret-token2. Protect All Admin Routes
// Always wrap route handlers with auth middleware
export const GET = authMiddleware(baseGET);
export const POST = authMiddleware(basePOST);3. Use Proper RBAC
const authMiddleware = createAuthMiddleware({
getAuthContext: async (request) => {
/* ... */
},
authorize: combineAuthAnd([
requireRoles(["admin"]),
requirePermissions(["policies:write"]),
]),
});4. Handle Errors Gracefully
function MyComponent() {
const { policies, error, refetch } = usePolicies();
if (error) {
return (
<div>
<p>Error: {error.message}</p>
<button onClick={() => refetch()}>Retry</button>
</div>
);
}
return <div>{/* ... */}</div>;
}Examples
For complete working examples, see:
Related Packages
- @devcraft-ts/abac-admin-core - Framework-agnostic core (required)
- @devcraft-ts/abac-admin-react - React hooks (included)
- @devcraft-ts/abac-admin-react-ui - Pre-built UI components (optional)
Contributing
Contributions are welcome! Please read our Contributing Guide.
License
MIT © [astralstriker]
Support
Built with ❤️ for Next.js developers who need powerful ABAC policy administration.
