
Access Control Rbac
Wire Spring Security HTTP rules and method security so REST APIs enforce roles and fine-grained permissions.
Overview
Access-control-rbac is an agent skill for the Ship phase that scaffolds Java Spring Security RBAC with role- and authority-based HTTP authorization.
Install
npx skills add https://github.com/aj-geddes/useful-ai-prompts --skill access-control-rbacWhat is this skill?
- Spring `SecurityFilterChain` with public, role (`hasRole`), and authority (`hasAuthority`) matchers
- Separate path patterns for admin, users, and CRUD-style post endpoints
- `@EnableGlobalMethodSecurity(prePostEnabled = true)` for method-level RBAC
- Copy-paste Java package layout (`com.example.security.RBACConfiguration`)
- Authenticated default with explicit permit-all for `/api/public/**`
Adoption & trust: 519 installs on skills.sh; 251 GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
You have Spring Boot API routes but no clear, consistent pattern for roles, permissions, and public versus protected paths.
Who is it for?
Indie builders adding ADMIN/USER roles and resource-scoped authorities to an existing Spring REST API before go-live.
Skip if: Teams needing OAuth2/OIDC login, multi-tenant ABAC, or non-Spring stacks—this snippet is Spring Security–centric only.
When should I use this skill?
Scaffolding or updating Spring Boot API security with roles and per-resource authorities.
What do I get? / Deliverables
Your agent produces a `SecurityFilterChain` configuration with explicit matchers and method security enabled so endpoints map to roles and authorities you can extend.
- RBACConfiguration.java-style SecurityFilterChain bean
- Documented path-to-role/authority mapping
Recommended Skills
Journey fit
Access control and RBAC hardening belong on the Ship shelf under Security—right before or alongside launch when APIs must enforce who can call what. The skill is almost entirely Spring SecurityFilterChain and authority strings (`posts:read`, `ROLE_ADMIN`), which is application security configuration, not generic backend CRUD.
How it compares
A focused RBAC template snippet, not a full identity provider integration or generic security audit skill.
Common Questions / FAQ
Who is access-control-rbac for?
Solo and indie builders on Spring Boot who want agent help wiring standard RBAC matchers and method security without reading the entire Spring Security reference first.
When should I use access-control-rbac?
During Ship when you are locking down `/api/admin/**`, user routes, and CRUD post endpoints, or during Build backend work when you first introduce Spring Security to the project.
Is access-control-rbac safe to install?
Treat generated security config as code you must review: confirm matchers match your real routes, enable CSRF/session policies appropriately, and check the Security Audits panel on this Prism page before trusting the repo.
SKILL.md
READMESKILL.md - Access Control Rbac
# Java Spring Security RBAC ## Java Spring Security RBAC ```java // RBACConfiguration.java package com.example.security; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.web.SecurityFilterChain; @Configuration @EnableGlobalMethodSecurity(prePostEnabled = true) public class RBACConfiguration { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(authz -> authz // Public endpoints .requestMatchers("/api/public/**").permitAll() // Role-based access .requestMatchers("/api/admin/**").hasRole("ADMIN") .requestMatchers("/api/users/**").hasAnyRole("USER", "ADMIN") // Permission-based access .requestMatchers("/api/posts/**").hasAuthority("posts:read") .requestMatchers("/api/posts/create").hasAuthority("posts:create") .requestMatchers("/api/posts/*/edit").hasAuthority("posts:update") .requestMatchers("/api/posts/*/delete").hasAuthority("posts:delete") // Default .anyRequest().authenticated() ) .csrf().disable(); return http.build(); } } // UserController.java with method-level security import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/api/users") public class UserController { @GetMapping("/{id}") @PreAuthorize("hasRole('ADMIN') or #id == authentication.principal.id") public User getUser(@PathVariable String id) { // Users can view their own profile or admins can view any return userService.findById(id); } @PutMapping("/{id}") @PreAuthorize("@accessControl.canUpdateUser(authentication, #id)") public User updateUser(@PathVariable String id, @RequestBody User user) { return userService.update(id, user); } @DeleteMapping("/{id}") @PreAuthorize("hasRole('ADMIN')") public void deleteUser(@PathVariable String id) { userService.delete(id); } } // AccessControlService.java - Custom permission logic @Service public class AccessControlService { public boolean canUpdateUser(Authentication auth, String userId) { // Admins can update anyone if (auth.getAuthorities().stream() .anyMatch(a -> a.getAuthority().equals("ROLE_ADMIN"))) { return true; } // Users can update themselves return auth.getPrincipal().equals(userId); } public boolean canApproveExpense(Authentication auth, Expense expense) { UserDetails user = (UserDetails) auth.getPrincipal(); // Check if user is manager if (!auth.getAuthorities().stream() .anyMatch(a -> a.getAuthority().equals("ROLE_MANAGER"))) { return false; } // Check department match return user.getDepartment().equals(expense.getDepartment()); } } ``` # Node.js RBAC System ## Node.js RBAC System ```javascript // rbac-system.js class Permission { constructor(resource, action) { this.resource = resource; this.action = action; } toString() { return `${this.resource}:${this.action}`; } } class Role { constructor(name, description) { this.name = name; this.description = description; this.permissions = new Set(); this.inherits = new Set(); } addPermission(permission) { this.permissions.add(permission.toString()); } removePermission(permission) { this.permissions.delete(permission.toString()); } inheritFrom(role) { this.inherits.add(r