Hook — why this matters now
Building a modern app means splitting responsibilities: Laravel for API and Next.js for the UI. That split introduces a tough question: how do you keep authorization centralized, secure, and easy to reason about across backend and frontend? Implementing RBAC correctly solves that — it gives you predictable access control and a clean UX without duplicated logic.
The problem in one sentence
You need fine-grained access rules (who can edit, who can delete, who can see what) enforced server-side, while the frontend adapts UI and navigation based on the same rules — without trusting the client.
High-level solution
Use a battle-tested RBAC library on Laravel and expose only the necessary role/permission info to Next.js. Protect API routes in Laravel, and use the exposed user data in Next.js to conditionally render UI and protect pages server-side.
Key components:
- Laravel authentication (Sanctum recommended for SPAs)
- spatie/laravel-permission for roles & permissions
- Next.js auth (NextAuth.js or custom) that stores tokens securely
- Backend middleware + frontend checks for a layered defense
Step-by-step implementation (practical)
-
Set up API auth
- Use Laravel Breeze with the API option or Sanctum to issue tokens suitable for a SPA.
- Example command: composer require laravel/breeze --dev and php artisan breeze:install api.
-
Install roles/permissions
- Use spatie/laravel-permission, publish its migrations and run them.
- Add Spatie’s HasRoles trait to your User model so users can be assigned roles and permissions.
-
Seed roles and permissions
- Seed roles like admin, editor, user and permissions like edit articles, delete users.
- Give the admin role the appropriate permissions so checks are straightforward.
-
Protect backend routes with middleware
- Use middleware such as auth:sanctum and role:admin or permission:edit articles on sensitive routes.
- Example: Route::middleware(['auth:sanctum','role:admin'])->get('/admin/dashboard', ...).
-
Expose minimal user info to the frontend
- Return id, name, roles (getRoleNames()) and permissions (getAllPermissions()->pluck('name')) from your user resource so the frontend can adapt UI. Don’t return secrets or token internals.
-
Authenticate Next.js and fetch the user
- Authenticate via token-based flow (Sanctum tokens / Passport). Store tokens in HttpOnly cookies when possible to reduce XSS risk.
- After login, fetch /api/user (or your profile endpoint) with the token and use roles/permissions to decide UI and routing.
Protect the frontend too (but don’t trust it)
Frontend checks are for UX and early redirect; authorization must remain server-side. Use server-side rendering or getServerSideProps to validate access for pages like an admin dashboard. Example logic: if user.roles does not include 'admin', redirect to /not-authorized.
Quick best practices for developers
- Centralize role/permission logic in Laravel; use policies when you need model-level checks.
- Send only the data the UI needs — id, roles, and permissions are usually enough.
- Store tokens in HttpOnly cookies where feasible; avoid localStorage for long-lived tokens.
- Invalidate tokens on logout or password change.
- Regularly audit role assignments and prefer least-privilege defaults.
Common pitfalls and how to avoid them
- Token expiry confusion: implement refresh logic or force sign-in when a token expires.
- Stale roles in client sessions: re-fetch user profile on sensitive actions or after role changes.
- Over-relying on frontend checks: always enforce permission checks in controllers, policies, or middleware.
- CORS/CSRF headaches: plan your CORS and Sanctum CSRF flow upfront when backend and frontend are on different domains.
Example flow in plain terms
User logs in from Next.js → Laravel issues a token (or sets a cookie) → Next.js fetches the user profile with roles and permissions → Backend routes enforce middleware checks for every protected API call → Next.js uses the profile to show/hide UI and uses server-side redirects for protected pages.
Where to learn more and examples
If you want a full walkthrough, examples, and templates, check out the case study at https://prateeksha.com/blog/role-based-access-control-laravel-nextjs-frontend. More resources and projects are available at https://prateeksha.com/blog and the company site https://prateeksha.com.
Final thoughts
RBAC isn’t just about locking pages — it’s about clear, maintainable rules that live where they belong: on the server. Pair that with pragmatic frontend checks for a smoother UX and you get secure, scalable apps that won’t surprise you as they grow. If you need help implementing RBAC across Laravel and Next.js, the team at Prateeksha Web Design has real-world experience and templates to accelerate your build.
Top comments (0)