Help us improve
Share bugs, ideas, or general feedback.
From grimoire
Enforces deny-by-default authorization at every resource access point using RBAC or ABAC patterns. Use when implementing access control decisions for APIs, web apps, or services.
npx claudepluginhub jeffreytse/grimoire --plugin grimoireHow this skill is triggered — by the user, by Claude, or both
Slash command
/grimoire:apply-authorization-controlThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Enforce explicit, deny-by-default authorization at every resource access point using Role-Based (RBAC) or Attribute-Based (ABAC) access control — never relying on UI hiding or obscurity as security.
Guides designing role-based access control (RBAC) systems with permission modeling, role definitions, and resource-level checks to prevent authorization failures.
Guides selection and implementation of authorization models including RBAC, ABAC, ACL, ReBAC, and policy-as-code for permission systems and access control design.
Design authorization systems (access control, role-based permissions, principle of least privilege) to enforce fine-grained access policies.
Share bugs, ideas, or general feedback.
Enforce explicit, deny-by-default authorization at every resource access point using Role-Based (RBAC) or Attribute-Based (ABAC) access control — never relying on UI hiding or obscurity as security.
Adopted by: OWASP API Security Top 10 2023 lists Broken Object Level Authorization (API1), Broken Object Property Level Authorization (API3), and Broken Function Level Authorization (API5) as the top API vulnerability classes — all caused by missing or incomplete authorization checks. NIST SP 800-162 defines ABAC as the federal standard for fine-grained access control. AWS IAM, Google Cloud IAM, and Azure RBAC all implement these patterns at cloud scale. PCI DSS v4.0 Requirement 7 mandates least-privilege access control. Impact: OWASP reports that broken access control was the #1 web vulnerability in 2021 (A01). Broken Object Level Authorization is the top API vulnerability in 2023 — it allows any authenticated user to access any other user's data by changing an ID in the request. Dropbox's 2012 breach and Instagram's 2019 BOLA vulnerability both stemmed from missing object-level authorization. Proper authorization prevents entire classes of data exposure. Why best: UI-level hiding (not rendering a button) and security through obscurity (unlinked URLs) are the common alternatives — they provide zero protection against direct API calls. Explicit server-side authorization checks enforced on every request are the only reliable defense.
Sources: OWASP Authorization Cheat Sheet; OWASP API Security Top 10 2023; NIST SP 800-162; CWE-285
Default deny: every resource access must pass an explicit authorization check:
def get_document(doc_id, current_user):
doc = db.get(doc_id)
if doc is None:
raise NotFound()
# Explicit ownership/permission check — never skip this
if doc.owner_id != current_user.id and not current_user.has_role('admin'):
raise Forbidden()
return doc
Never assume that authenticated = authorized. Every object-level fetch needs a check.
Implement Role-Based Access Control (RBAC) for function-level permissions:
# Define roles and their permitted actions
ROLE_PERMISSIONS = {
'viewer': {'document:read'},
'editor': {'document:read', 'document:write'},
'admin': {'document:read', 'document:write', 'document:delete', 'user:manage'},
}
def require_permission(permission):
def decorator(func):
def wrapper(*args, **kwargs):
if permission not in ROLE_PERMISSIONS.get(current_user.role, set()):
raise Forbidden(f"Requires {permission}")
return func(*args, **kwargs)
return wrapper
return decorator
@require_permission('document:delete')
def delete_document(doc_id):
...
For multi-tenancy: always scope queries by owner/tenant — never return all records and filter in application code:
# BAD — fetches all, filters in Python (BOLA if filter fails)
all_docs = db.query("SELECT * FROM documents")
user_docs = [d for d in all_docs if d.owner_id == current_user.id]
# GOOD — database enforces ownership
user_docs = db.query(
"SELECT * FROM documents WHERE owner_id = %s",
(current_user.id,)
)
Validate field-level access for sensitive attributes (Broken Object Property Level Authorization):
# Define which fields each role can read/write
FIELD_READ_PERMISSIONS = {
'viewer': {'id', 'title', 'content', 'created_at'},
'admin': {'id', 'title', 'content', 'created_at', 'owner_id', 'internal_notes'},
}
def serialize_document(doc, user_role):
allowed = FIELD_READ_PERMISSIONS.get(user_role, set())
return {k: v for k, v in doc.items() if k in allowed}
Apply ABAC for fine-grained, context-aware decisions:
def can_edit(user, document, context):
# Attribute-based: combine user attributes, resource attributes, context
if user.department != document.department:
return False
if context.time_of_day not in document.allowed_hours:
return False
if document.classification_level > user.clearance_level:
return False
return True
Use a centralized authorization library — don't scatter if user.role == 'admin' checks:
casbin (RBAC/ABAC policy engine)casl, node-casbin@PreAuthorize)from casbin import Enforcer
e = Enforcer('model.conf', 'policy.csv')
if not e.enforce(user.id, resource, action):
raise Forbidden()
Log all authorization failures — repeated failures indicate probing:
if not authorized:
logger.warning("authz_denied",
user_id=current_user.id,
resource=resource_id,
action=action,
ip=request.remote_addr)
raise Forbidden()
PATCH /api/documents with an array body needs per-document ownership checks, not just route-level RBAC.