CREATE TABLE roles (id SERIAL PRIMARY KEY, name TEXT UNIQUE);CREATE TABLE permissions (id SERIAL PRIMARY KEY, name TEXT UNIQUE);CREATE TABLE role_permissions ( role_id INT REFERENCES roles, permission_id INT REFERENCES permissions, PRIMARY KEY (role_id, permission_id));CREATE TABLE user_roles ( user_id BIGINT, role_id INT, granted_at TIMESTAMPTZ, granted_by BIGINT, PRIMARY KEY (user_id, role_id));
@PreAuthorize("hasAuthority('orders:write')")public Order create(...) { ... }// Or programmaticif (!authService.hasPermission(user, "orders", "write", orderId)) throw new AccessDeniedException();
7. Implementing Role-Based Routing
Layer
Implementation
Express
router.use("/admin", requireRole("admin"))
Spring
@PreAuthorize("hasRole('ADMIN')")
Next.js
middleware.ts — redirect if role missing
React Router
Guarded route component
8. Using Role-Based UI Rendering
Example: React permission gate
function Can({ permission, children }) { const { permissions } = useAuth(); return permissions.includes(permission) ? children : null;}<Can permission="orders:delete"> <DeleteButton /></Can>
Warning: UI-only gating is for UX. ALWAYS enforce permissions server-side.
9. Implementing Dynamic Role Assignment
Pattern
Use
JIT from IdP
Provision on first login from group claim
Self-service request
Workflow with approvals
Time-bound elevation
"Sudo" mode for 30 min
Auto-revoke
Inactivity-based deprovisioning
10. Managing Role Conflicts
Conflict
Resolution
SoD (Separation of Duties)
Static: cannot hold both; Dynamic: cannot use both in same session