# Coldbox Security Authorization

> Use this skill when implementing authorization in ColdBox with CBSecurity, defining security rules for events and URLs, checking user roles with cbsecurity.has(), checking permissions with cbsecurity.can(), implementing role-based route protection, using @secured annotations on handler actions, or blocking unauthorized access.

- Skill: `coldbox/coldbox-security-authorization` (Agent Skill)
- Install (CLI): `npx skillmds@latest add coldbox/coldbox-security-authorization`
- Raw SKILL.md: https://api.skillmd.com/api/skills/coldbox/coldbox-security-authorization/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Security
- Author: ColdBox (https://skillmd.com/u/coldbox)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/coldbox/coldbox-security-authorization

---


# Authorization Patterns in ColdBox

## Overview

Authorization in ColdBox is handled by CBSecurity through security rules, role checks, permission checks, and handler-level annotations. It determines what authenticated users can access.

## Language Mode Reference

Examples use **BoxLang (`.bx`)** syntax by default. Adapt for your target language:

| Concept | BoxLang (`.bx`) | CFML (`.cfc`) |
|---------|-----------------|---------------|
| Class declaration | `class [extends="..."] {` | `component [extends="..."] {` |
| DI annotation | `@inject` above `property name="svc";` | `property name="svc" inject="svc";` |
| View templates | `.bxm` suffix | `.cfm` / `.cfml` suffix |
| Tag prefix | `<bx:if>`, `<bx:output>`, `<bx:set>` | `<cfif>`, `<cfoutput>`, `<cfset>` |

> **CFML Compat Mode**: With BoxLang + CFML Compat module, `.bx` and `.cfc` files coexist freely. BoxLang-native classes use `class {}` (`.bx` files); CFML-compat classes use `component {}` (`.cfc` files).

## CBSecurity Rules

### Event-Based Rules

```boxlang
// config/ColdBox.cfc
moduleSettings = {
    cbsecurity: {
        rules: [
            // Secure specific event
            {
                secureList: "admin.index",
                match: "event",
                roles: "admin",
                action: "redirect",
                redirect: "/login"
            },
            // Secure multiple events
            {
                secureList: "users.edit,users.delete",
                match: "event",
                roles: "admin",
                action: "block"
            },
            // Regex pattern for all admin events
            {
                secureList: "^admin\\.",
                match: "event",
                roles: "admin,superadmin",
                action: "redirect",
                redirect: "/login"
            },
            // Public whitelist
            {
                secureList: "main\\.index,auth\\..*",
                whiteList: true,
                match: "event"
            }
        ]
    }
}
```

### URL-Based Rules

```boxlang
rules: [
    {
        secureList: "/admin",
        match: "url",
        roles: "admin",
        action: "redirect"
    },
    {
        secureList: "^/api/.*",
        match: "url",
        roles: "api_user",
        action: "block",
        statusCode: 401
    }
]
```

## Role and Permission Checking in Handlers

```boxlang
class extends="coldbox.system.EventHandler" {

    property name="cbsecurity" inject="@cbsecurity"

    function edit( event, rc, prc ) {
        // Single role check
        if ( !cbsecurity.has( "admin" ) ) {
            cbsecurity.block( "Admin access required" )
        }

        // OR logic — any of these roles passes
        if ( !cbsecurity.has( "admin,manager" ) ) {
            cbsecurity.block( "Insufficient privileges" )
        }

        // AND logic — user must have all these roles
        if ( !cbsecurity.all( "admin,moderator" ) ) {
            cbsecurity.block( "Need both admin and moderator roles" )
        }

        // Permission check
        if ( !cbsecurity.can( "users.edit" ) ) {
            cbsecurity.block( "Missing permission: users.edit" )
        }

        event.setView( "users/edit" )
    }
}
```

**CFML (`.cfc`):**

```cfml
component extends="coldbox.system.EventHandler" {

    property name="cbsecurity" inject="@cbsecurity"

    function edit( event, rc, prc ) {
        // Single role check
        if ( !cbsecurity.has( "admin" ) ) {
            cbsecurity.block( "Admin access required" )
        }

        // OR logic — any of these roles passes
        if ( !cbsecurity.has( "admin,manager" ) ) {
            cbsecurity.block( "Insufficient privileges" )
        }

        // AND logic — user must have all these roles
        if ( !cbsecurity.all( "admin,moderator" ) ) {
            cbsecurity.block( "Need both admin and moderator roles" )
        }

        // Permission check
        if ( !cbsecurity.can( "users.edit" ) ) {
            cbsecurity.block( "Missing permission: users.edit" )
        }

        event.setView( "users/edit" )
    }
}
```

## @secured Annotation (Handler-Level)

```boxlang
/**
 * Secure entire handler (all actions require login)
 * @secured
 */
class extends="coldbox.system.EventHandler" {

    /**
     * Requires admin role
     * @secured admin
     */
    function deleteUser( event, rc, prc ) {
        // Only admin role gets here
    }

    /**
     * Requires specific permission
     * @secured users.create
     */
    function create( event, rc, prc ) {
        // Only users with users.create permission get here
    }

    /**
     * Requires role AND permission
     * @secured admin,users.delete
     */
    function destroy( event, rc, prc ) {
        // Requires admin role AND users.delete permission
    }
}
```

**CFML (`.cfc`):**

```cfml
/**
 * Secure entire handler (all actions require login)
 * @secured
 */
component extends="coldbox.system.EventHandler" {

    /**
     * Requires admin role
     * @secured admin
     */
    function deleteUser( event, rc, prc ) {
        // Only admin role gets here
    }

    /**
     * Requires specific permission
     * @secured users.create
     */
    function create( event, rc, prc ) {
        // Only users with users.create permission get here
    }

    /**
     * Requires role AND permission
     * @secured admin,users.delete
     */
    function destroy( event, rc, prc ) {
        // Requires admin role AND users.delete permission
    }
}
```

## Resource-Based Authorization

```boxlang
class extends="coldbox.system.EventHandler" {

    property name="cbsecurity"  inject="@cbsecurity"
    property name="postService" inject="PostService"
    property name="auth"        inject="AuthenticationService@cbauth"

    function edit( event, rc, prc ) {
        event.paramValue( "id", 0 )
        prc.post = postService.findById( rc.id )

        // Resource-owner check (user owns this resource)
        if ( prc.post.authorId != auth.getUserId() && !cbsecurity.has( "admin" ) ) {
            cbsecurity.block( "You can only edit your own posts" )
        }

        event.setView( "posts/edit" )
    }
}
```

**CFML (`.cfc`):**

```cfml
component extends="coldbox.system.EventHandler" {

    property name="cbsecurity"  inject="@cbsecurity"
    property name="postService" inject="PostService"
    property name="auth"        inject="AuthenticationService@cbauth"

    function edit( event, rc, prc ) {
        event.paramValue( "id", 0 )
        prc.post = postService.findById( rc.id )

        // Resource-owner check (user owns this resource)
        if ( prc.post.authorId != auth.getUserId() && !cbsecurity.has( "admin" ) ) {
            cbsecurity.block( "You can only edit your own posts" )
        }

        event.setView( "posts/edit" )
    }
}
```

## Permission-Based Authorization

```boxlang
// models/User.cfc — user entity with roles/permissions
class {

    property name="id"
    property name="name"
    property name="roles" default=""
    property name="permissions" default=""

    function hasRole( required role ) {
        return listContains( variables.roles, arguments.role )
    }

    function can( required permission ) {
        return listContains( variables.permissions, arguments.permission )
    }

    function getRolesList() {
        return listToArray( variables.roles )
    }
}
```

**CFML (`.cfc`):**

```cfml
// models/User.cfc — user entity with roles/permissions
component {

    property name="id"
    property name="name"
    property name="roles" default=""
    property name="permissions" default=""

    function hasRole( required role ) {
        return listContains( variables.roles, arguments.role )
    }

    function can( required permission ) {
        return listContains( variables.permissions, arguments.permission )
    }

    function getRolesList() {
        return listToArray( variables.roles )
    }
}
```

## Firewall Configuration

```boxlang
moduleSettings = {
    cbsecurity: {
        firewall: {
            enabled: true,
            // "redirect" for web apps, "block" for APIs
            defaultAuthenticationAction: "redirect",
            defaultAuthorizationAction: "redirect",
            // Status code when action = "block"
            statusCode: 401,
            // Override rejection handler
            invalidAuthenticationEvent: "auth.login",
            invalidAuthorizationEvent: "main.accessDenied"
        }
    }
}
```

## View-Level Authorization

```html
<!-- Show/hide UI based on role -->
<cfif cbsecurity.has( "admin" )>
    <a href="#event.buildLink( 'admin.index' )#">Admin Panel</a>
</cfif>

<cfif cbsecurity.can( "users.create" )>
    <a href="#event.buildLink( 'users.create' )#">Add User</a>
</cfif>

<cfif auth.isLoggedIn()>
    <span>Welcome, #auth.getUser().name#</span>
</cfif>
```

## CBSecurity Method Reference

| Method | Description |
|--------|-------------|
| `cbsecurity.has( "role" )` | Check if user has role (OR for comma list) |
| `cbsecurity.all( "role1,role2" )` | Check if user has ALL roles (AND) |
| `cbsecurity.can( "permission" )` | Check if user has specific permission |
| `cbsecurity.block( message )` | Block/reject current request |
| `cbsecurity.isLoggedIn()` | Check authentication status |
| `cbsecurity.getUser()` | Get authenticated user |
| `cbsecurity.isAdmin()` | Check if user is admin |

