### Install cbsecurity Module Source: https://github.com/coldbox-modules/cbsecurity/wiki/Home Use CommandBox to install the cbsecurity module into your project. ```bash box install cbsecurity ``` -------------------------------- ### Permissions Configuration Source: https://github.com/coldbox-modules/cbsecurity/wiki/Third-Rule-Analysis Specifies granular permissions for accessing resources. No permissions are defined in this example. ```xml ``` -------------------------------- ### Whitelist Configuration Source: https://github.com/coldbox-modules/cbsecurity/wiki/Second-Rule-Analysis The `` element is used to define events that should bypass security checks. No events are defined in this example, meaning no events are whitelisted. ```xml ``` -------------------------------- ### Real Sample CFLogin with Authentication Source: https://github.com/coldbox-modules/cbsecurity/wiki/Default-Security This example shows a practical implementation of cflogin where user authentication is performed using a service layer before logging the user in. It retrieves username, password, and roles from the service. ```html ``` -------------------------------- ### Secure List URI Pattern Source: https://github.com/coldbox-modules/cbsecurity/wiki/Third-Rule-Analysis Secures any incoming URI that starts with the specified pattern. This example secures URIs starting with '/secured'. ```xml /secured.* ``` -------------------------------- ### Security Rule Anatomy Example Source: https://github.com/coldbox-modules/cbsecurity/blob/development/readme.md Defines the structure of a security rule, outlining available properties for access control configuration. All properties are optional except 'secureList'. ```javascript rules = [ { "whitelist" : "", // A list of white list events or Uri's "securelist" : "", // A list of secured list events or Uri's "match" : "event", // Match the event or a url "roles" : "", // Attach a list of roles to the rule "permissions" : "", // Attach a list of permissions to the rule "redirect" : "", // If rule breaks, and you have a redirect it will redirect here "overrideEvent" : "", // If rule breaks, and you have an event, it will override it "useSSL" : false, // Force SSL, "action" : "", // The action to use (redirect|override|block) when no redirect or overrideEvent is defined in the rule. "module" : "", // metadata we can add so mark rules that come from modules "httpMethods" : "*", // Match all HTTP methods or particular ones as a list "allowedIPs" : "*" // The rule only matches if the IP list matches. It can be a list of IPs to match. }; ] ``` -------------------------------- ### Sample Permission-Based Security Validators Source: https://github.com/coldbox-modules/cbsecurity/blob/development/readme.md Provides a concrete implementation of ruleValidator and annotationValidator using a private permissionValidator function. This example checks user authentication and permissions before granting access. ```javascript struct function ruleValidator( required rule, required controller ){ return permissionValidator( rule.permissions, controller, rule ); } struct function annotationValidator( required securedValue, required controller ){ return permissionValidator( securedValue, controller ); } private function permissionValidator( permissions, controller, rule ){ var results = { "allow" : false, "type" : "authentication", "messages" : "" }; var user = security.getCurrentUser(); // First check if user has been authenticated. if( user.isLoaded() AND user.isLoggedIn() ){ // Do we have the right permissions if( len( arguments.permissions ) ){ results.allow = user.checkPermission( arguments.permission ); results.type = "authorization"; } else { results.allow = true; } } return results; } ``` -------------------------------- ### Get Real Host Name Source: https://context7.com/coldbox-modules/cbsecurity/llms.txt Retrieve the actual host name, accounting for `X-Forwarded-Host` headers. ```javascript // Get the real host (handles x-forwarded-host) var host = cbSecure().getRealHost(); ``` -------------------------------- ### User Validator Implementation in CFML Source: https://github.com/coldbox-modules/cbsecurity/wiki/Custom-Security-Validator-Object A CFML example demonstrating a user validator function. It checks session user authorization and iterates through permissions defined in the rule to determine access. ```cfml ``` -------------------------------- ### Securelist Configuration Source: https://github.com/coldbox-modules/cbsecurity/wiki/Second-Rule-Analysis Configure the `` element to define events that require security validation. Events matching the pattern (e.g., starting with 'moderator') will be secured. ```xml ^moderator ``` -------------------------------- ### Refresh Tokens via API (cURL) Source: https://context7.com/coldbox-modules/cbsecurity/llms.txt Example of how to refresh JWT tokens using a cURL command. This demonstrates the API endpoint and expected request/response format. ```bash # Refresh tokens via API curl -X POST https://myapp.com/cbsecurity/refreshtoken \ -H "x-refresh-token: eyJhbGciOiJIUzUxMiIs..." # Response on success { "data": { "access_token": "eyJhbGciOiJIUzUxMiIs...", "refresh_token": "eyJhbGciOiJIUzUxMiIs..." }, "messages": ["Tokens refreshed! The passed in refresh token has been invalidated"] } ``` -------------------------------- ### Annotation-Based Handler Security Source: https://context7.com/coldbox-modules/cbsecurity/llms.txt Secure entire ColdBox handlers by applying the 'secured' annotation. This example shows securing a handler for authenticated users. ```js // Secure entire handler - requires authentication component secured { function index( event, rc, prc ) { // Only authenticated users can access } function list( event, rc, prc ) { // Also requires authentication } } ``` -------------------------------- ### User Validator Implementation in CFScript Source: https://github.com/coldbox-modules/cbsecurity/wiki/Custom-Security-Validator-Object A CFScript example of a user validator function. It mirrors the CFML logic, checking authorization and user permissions against the provided rule. ```cfscript /** * User Validator for security * * @hint Verifies that the user is in any permission * @rule.hint The rule to verify * @controller.hint The ColdBox controller */ public boolean function userValidator( required struct rule, required any controller ) { // Local call to get the user object from the session var user = getUserSession(); // Authorized Check, if true, then see if user is valid. This column is an additional column in my query if ( arguments.rule['authorize_check'] and user.getIsAuthorized() ) { return true; } // Loop Over Permissions to see if my user is in any of them. var permissionsArray = ListToArray(arguments.rule['permissions']); for (var permission in permissionsArray) { // My user object has a method called check permission that I call with a permission to validate if ( user.checkPermission( permission ) ) { // This permission existed, I only need one to match as per my business logic, so let's return and move on return true; } } // If we got here, the user does not have permission return false; } ``` -------------------------------- ### Annotation-Based Action Security Source: https://context7.com/coldbox-modules/cbsecurity/llms.txt Apply specific security requirements to individual actions within a handler using the 'secured' annotation. This example demonstrates handler-level and action-level security overrides. ```js // Secure with specific permissions component secured="admin" { // Requires admin permission at handler level function index( event, rc, prc ) { } // Override with specific action permission function edit( event, rc, prc ) secured="users:edit" { } // Requires users:delete permission function delete( event, rc, prc ) secured="users:delete" { } } ``` ```js // Mixed security - handler and action level component secured="authenticated" { // Public action within secured handler function publicAction( event, rc, prc ) secured=false { } // Cascading security: user must have 'authenticated' AND 'reports:view' function viewReport( event, rc, prc ) secured="reports:view" { } } ``` -------------------------------- ### Run MySQL Database with Docker for cbsecurity Tests Source: https://github.com/coldbox-modules/cbsecurity/blob/development/readme.md Use this Docker command to set up a MySQL instance, map the port, set the root password, create a database named 'cbsecurity', and mount the SQL initialization script. This is essential for running the project's tests. ```sh docker run -d \ --name=cbsecurity \ -p 3306:3306 \ -e MYSQL_ROOT_PASSWORD=mysql \ -e MYSQL_DATABASE=cbsecurity \ -v $(pwd)/test-harness/tests/resources/cbsecurity.sql:/docker-entrypoint-initdb.d/cbsecurity.sql \ mysql:5 ``` -------------------------------- ### Secure Execution with Exceptions (All Permissions) Source: https://context7.com/coldbox-modules/cbsecurity/llms.txt Use `cbSecure().secureAll()` to enforce that a user must have all specified permissions. If any permission is missing, a `NotAuthorized` exception is thrown. ```javascript function manageUsers( event, rc, prc ) { cbSecure().secureAll( "users:read,users:write,users:delete" ); // User must have all three permissions } ``` -------------------------------- ### Configure CbSecurity Interceptor with JSON Rules Source: https://github.com/coldbox-modules/cbsecurity/wiki/JSON-Properties Use this configuration to set up the ApplicationSecurity interceptor when your security rules are defined in a JSON file. Ensure the `rulesFile` path is correct. ```javascript interceptors = [ {class="cbsecurity.interceptors.Security", name="ApplicationSecurity", properties={ useRegex = true, rulesSource = "json", validatorModel = "SecurityService", rulesFile = "config/security.json.cfm" }} ]; ``` -------------------------------- ### Role-Based Access Control Source: https://github.com/coldbox-modules/cbsecurity/wiki/Third-Rule-Analysis Defines the roles that are allowed to access secured URLs. Users with 'admin' and 'paid_subscriber' roles can access URLs starting with '/secured'. ```xml admin,paid_subscriber ``` -------------------------------- ### Check User Permissions (AND Logic) Source: https://context7.com/coldbox-modules/cbsecurity/llms.txt Use `cbSecure().all()` to verify if a user has all of the specified permissions. Permissions can be provided as a comma-separated string or an array. ```javascript if ( cbSecure().all( "users:read,users:write" ) ) { // User has BOTH users:read AND users:write } if ( cbSecure().all( [ "reports:view", "reports:export" ] ) ) { // User has both permissions } ``` -------------------------------- ### Secure Execution with Exceptions (None Permissions) Source: https://context7.com/coldbox-modules/cbsecurity/llms.txt Use `cbSecure().secureNone()` to ensure a user does not have any of the specified permissions. If the user has any of the listed permissions, a `NotAuthorized` exception is thrown. ```javascript function publicOnlyAction( event, rc, prc ) { cbSecure().secureNone( "admin,moderator" ); // Only non-admin/non-moderator users can access } ``` -------------------------------- ### Use Delegates for User Objects in ColdBox 7+ Source: https://context7.com/coldbox-modules/cbsecurity/llms.txt Leverage ColdBox 7+ delegates for cleaner user implementations. Delegates like `Auth`, `Authorizable`, and `JwtSubject` automatically provide various authentication and JWT-related methods. ```cfml // models/entities/User.cfc with delegates component accessors="true" delegates=" Auth@cbSecurity, Authorizable@cbSecurity, JwtSubject@cbSecurity " { property name="id"; property name="firstName"; property name="lastName"; property name="username"; property name="password"; property name="permissions"; property name="roles"; function init() { variables.id = ""; variables.firstName = ""; variables.lastName = ""; variables.username = ""; variables.password = ""; variables.permissions = []; variables.roles = []; return this; } // Delegates automatically provide: // - hasPermission() // - hasRole() // - hasAll() // - hasNone() // - sameUser() // - isLoggedIn() // - guest() // - getJwtCustomClaims() // - getJwtScopes() // - auth() // - jwtAuth() // - cbSecure() User function setRoles( roles ) { variables.roles = isArray( arguments.roles ) ? arguments.roles : listToArray( arguments.roles ); return this; } User function setPermissions( permissions ) { variables.permissions = isArray( arguments.permissions ) ? arguments.permissions : listToArray( arguments.permissions ); return this; } boolean function isLoaded() { return len( variables.id ) > 0; } } ``` -------------------------------- ### Configure Global Firewall Rules in ColdBox.cfc Source: https://github.com/coldbox-modules/cbsecurity/blob/development/readme.md Define global firewall settings, including default actions for invalid authentication or authorization, and a list of global security rules. These rules can specify whitelists, securelists, match criteria, roles, permissions, and actions like redirect or override. ```javascript // Module Settings moduleSettings = { // CB Security cbSecurity : { firewall : { // Global Relocation when invalid access is detected, instead of each rule declaring one. "invalidAuthenticationEvent" : "main.index", // Global override event when invalid access is detected, instead of each rule declaring one. "invalidAuthorizationEvent" : "main.index", // Default invalid action: override or redirect or block when invalid access is detected, default is to redirect "defaultAuthenticationAction" : "block", // Default invalid action: override or redirect or block when invalid access is detected, default is to redirect "defaultAuthorizationAction" : "redirect", // The global security rules as inline "rules" : [ // should use direct action and do a global redirect { "whitelist": "", "securelist": "admin", "match": "event", "roles": "admin", "permissions": "", "action" : "redirect" }, // no action, use global default action { "whitelist": "", "securelist": "noAction", "match": "url", "roles": "admin", "permissions": "" }, // Using overrideEvent only, so use an explicit override { "securelist": "ruleActionOverride", "match": "url", "overrideEvent": "main.login" }, // direct action, use global override { "whitelist": "", "securelist": "override", "match": "url", "roles": "", "permissions": "", "action" : "override" }, // Using redirect only, so use an explicit redirect { "securelist": "ruleActionRedirect", "match": "url", "redirect": "main.login" } ] } } }; ``` -------------------------------- ### Conditional Execution Based on Permissions (All) Source: https://context7.com/coldbox-modules/cbsecurity/llms.txt Use `cbSecure().whenAll()` to execute a `success` callback only if the user possesses all specified permissions. Permissions can be a comma-separated string or an array. ```javascript cbSecure().whenAll( permissions = [ "billing:view", "billing:edit" ], success = ( user, permissions ) => { prc.billingAccess = true; } ); ``` -------------------------------- ### Secure Execution with Exceptions (Single Permission) Source: https://context7.com/coldbox-modules/cbsecurity/llms.txt Use `cbSecure().secure()` to enforce a single permission. If the user lacks the permission, a `NotAuthorized` exception is thrown. ```javascript function editUser( event, rc, prc ) { cbSecure().secure( "users:edit" ); // Execution continues only if user has permission } ``` -------------------------------- ### Implement User Service for Authentication Providers Source: https://context7.com/coldbox-modules/cbsecurity/llms.txt Create a user service component to handle user retrieval for authentication providers. Inject UserGateway and a populator for entity population. This service is required for JWT and basic authentication. ```cfml component singleton accessors="true" { property name="userGateway" inject="UserGateway"; property name="populator" inject="wirebox:populator"; /** * Get user by ID (required for JWT authentication) */ User function retrieveUserById( required id ) { var userData = userGateway.findById( arguments.id ); if ( userData.recordCount ) { return populator.populateFromQuery( new models.entities.User(), userData ); } return new models.entities.User(); } /** * Get user by username (required for basic auth) */ User function retrieveUserByUsername( required username ) { var userData = userGateway.findByUsername( arguments.username ); if ( userData.recordCount ) { return populator.populateFromQuery( new models.entities.User(), userData ); } return new models.entities.User(); } /** * Validate credentials (required for basic auth) */ boolean function isValidCredentials( required username, required password ) { var user = retrieveUserByUsername( arguments.username ); if ( !user.isLoaded() ) { return false; } return bcrypt.checkPassword( arguments.password, user.getPassword() ); } } ``` -------------------------------- ### Check User Permissions (None Logic) Source: https://context7.com/coldbox-modules/cbsecurity/llms.txt Use `cbSecure().none()` to ensure a user does not possess any of the specified permissions. Permissions can be provided as a comma-separated string or an array. ```javascript if ( cbSecure().none( "banned,suspended" ) ) { // User does NOT have banned or suspended } ``` -------------------------------- ### Format Code with CommandBox Source: https://github.com/coldbox-modules/cbsecurity/blob/development/CONTRIBUTING.md Use these CommandBox scripts to format your code according to project standards. The 'format:watch' command automatically formats files as you save them. ```bash box run-script format ``` ```bash box run-script format: watch ``` -------------------------------- ### Get Real Client IP Address Source: https://context7.com/coldbox-modules/cbsecurity/llms.txt Retrieve the actual client IP address, correctly handling proxy headers. Use the optional `trustUpstream` parameter to disable proxy header trust if necessary. ```javascript // Get the real client IP address (handles proxies) var clientIP = cbSecure().getRealIP(); ``` ```javascript // With proxy trust disabled var directIP = cbSecure().getRealIP( trustUpstream = false ); ``` -------------------------------- ### Configure Security Interceptor with OCM Rules Source: https://github.com/coldbox-modules/cbsecurity/wiki/OCM-Properties Set up the ApplicationSecurity interceptor to use rules sourced from OCM, specifying the cache key for rule retrieval. ```javascript interceptors = [ {class="cbsecurity.interceptors.Security", name="ApplicationSecurity", properties={ useRegex = true, rulesSource = "ocm", validatorModel = "SecurityService", rulesOCMKey = "qSecurityRules" }} ]; ``` -------------------------------- ### Conditional Execution Based on Permissions (Single) Source: https://context7.com/coldbox-modules/cbsecurity/llms.txt Use `cbSecure().when()` to execute a `success` callback if the user has the specified permission, or a `fail` callback otherwise. Both callbacks receive the user and permissions. ```javascript cbSecure().when( permissions = "reports:view", success = ( user, permissions ) => { prc.reports = reportService.getAll(); }, fail = ( user, permissions ) => { prc.reports = []; prc.message = "You don't have access to reports"; } ); ``` -------------------------------- ### Configure HTTP Security Headers Source: https://context7.com/coldbox-modules/cbsecurity/llms.txt Enable and configure various HTTP security headers to protect against common web attacks. Ensure trustUpstream is set correctly if behind a proxy. ```javascript securityHeaders : { enabled : true, // Trust proxy headers (x-forwarded-*) trustUpstream : true, // Content Security Policy contentSecurityPolicy : { enabled : true, policy : "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self';" }, // Prevent MIME type sniffing contentTypeOptions : { enabled : true }, // Clickjacking protection frameOptions : { enabled : true, value : "SAMEORIGIN" // DENY, SAMEORIGIN, or ALLOW-FROM uri }, // HTTP Strict Transport Security hsts : { enabled : true, "max-age" : "31536000", // 1 year includeSubDomains : true, preload : true }, // Host header validation (prevent host header attacks) hostHeaderValidation : { enabled : true, allowedHosts : "myapp.com,www.myapp.com,api.myapp.com" }, // IP address validation ipValidation : { enabled : true, allowedIPs : "10.0.0.0/8,192.168.0.0/16,172.16.0.0/12" }, // Referrer policy referrerPolicy : { enabled : true, policy : "strict-origin-when-cross-origin" }, // Force SSL redirects secureSSLRedirects : { enabled : true }, // XSS protection header xssProtection : { enabled : true, mode : "block" }, // Custom headers customHeaders : { "X-Custom-Header" : "custom-value", "Permissions-Policy" : "geolocation=(), microphone=()" } } ``` -------------------------------- ### Match URL Pattern Source: https://github.com/coldbox-modules/cbsecurity/wiki/Third-Rule-Analysis Defines the incoming URL pattern to match after the domain name and application location. ```xml URL ``` -------------------------------- ### Configure Security Interceptor with XML Rules Source: https://github.com/coldbox-modules/cbsecurity/wiki/XML-Properties Use this configuration to enable the Security interceptor with rules loaded from an XML file. Ensure the 'rulesFile' path is correct relative to your application's configuration. ```javascript interceptors = [ {class="cbsecurity.interceptors.Security", name="ApplicationSecurity", properties={ useRegex = true, rulesSource = "xml", validatorModel = "SecurityService", rulesFile = "config/security.xml.cfm" }} ]; ``` -------------------------------- ### Configure cbsecurity Settings Source: https://github.com/coldbox-modules/cbsecurity/wiki/Home Define the 'cbsecurity' struct in your main ColdBox.cfc to configure module settings. These settings control regex usage, query checks, rule validation, and rule source locations. ```javascript cbsecurity = { // By default all rules are evulated as regular expressions useRegex = true, // Verify queries that they have all required columns, by default it is relaxed queryChecks = false, // Will verify rules of execute before ANY event. Be careful, can be intensive, usually the preProcess is enough. preEventSecurity = false, // The class path of a CFC that will validate rules, optional validator = "class.path", // The WireBox ID of the object to validate rules, optional validatorModel = "wireboxID", // The bean ID of the object in the ioc module that will validate the rules, optional validatorIOC = "beanID.from.ioc.module", // Where to look for security rules rulesSource = "xml,json,db,model,ioc,ocm", // The location of a rules file, aplies to XML and JSON only rulesFile = "path.to.file", // Rules DB Properties rulesDSN = "datasource", rulesTable = "table", rulesSQL = "select * from rulesTable", rulesOrderBy = "", // Model Rule Properties rulesModel = "wirebox.id", rulesModelMethod = "method", rulesModelArgs = "comma-delimmited list of args", // IOC properties rulesBean = "bean.id", rulesBeanMethod = "method", rulesBeanArgs = "comma-delimmited list of args", // Cache key that has rules in the 'default' provider rulesOCMKey = "key.from.default.provider" } ``` -------------------------------- ### Implement IAuthUser Interface in User Model Source: https://context7.com/coldbox-modules/cbsecurity/llms.txt Create user objects that implement the required authentication interface. Ensure the `getId`, `hasPermission`, and `hasRole` methods are defined. ```cfml component accessors="true" { property name="id"; property name="username"; property name="email"; property name="password"; property name="permissions"; property name="roles"; function init() { variables.id = ""; variables.permissions = []; variables.roles = []; return this; } // Required: Return unique identifier function getId() { return variables.id; } // Required: Check if user has permission(s) boolean function hasPermission( required permission ) { var permsToCheck = isArray( arguments.permission ) ? arguments.permission : listToArray( arguments.permission ); return permsToCheck .filter( ( perm ) => variables.permissions.findNoCase( perm ) ) .len() > 0; } // Required: Check if user has role(s) boolean function hasRole( required role ) { var rolesToCheck = isArray( arguments.role ) ? arguments.role : listToArray( arguments.role ); return rolesToCheck .filter( ( r ) => variables.roles.findNoCase( r ) ) .len() > 0; } // Helper: Check if user is loaded boolean function isLoaded() { return len( variables.id ) > 0; } } ``` -------------------------------- ### Configure cbsecurity Module Settings Source: https://context7.com/coldbox-modules/cbsecurity/llms.txt Configure the cbsecurity module in your ColdBox application's configuration file. This includes settings for authentication providers, basic authentication, firewall, visualizer, security headers, JWT, and CSRF protection. ```js moduleSettings = { cbauth = { userServiceClass = "models.services.UserService" }, cbsecurity = { // Authentication provider configuration authentication : { "provider" : "authenticationService@cbauth", "userService" : "", "prcUserVariable" : "oCurrentUser" }, // Basic auth with in-memory users basicAuth : { hashAlgorithm : "SHA-512", hashIterations : 5, users : { "admin" : { password : "admin123", permissions : [ "admin", "users:read", "users:write" ], roles : [ "admin" ] } } }, // Firewall configuration firewall : { autoLoadFirewall : true, validator : "AuthValidator@cbsecurity", handlerAnnotationSecurity : true, invalidAuthenticationEvent : "security.login", defaultAuthenticationAction : "redirect", invalidAuthorizationEvent : "security.unauthorized", defaultAuthorizationAction : "redirect", rules : { useRegex : true, useSSL : false, defaults : {}, inline : [], provider : { source : "", properties : {} } }, logs : { enabled : false, dsn : "myDatasource", schema : "", table : "cbsecurity_logs", autoCreate : true } }, // Security visualizer visualizer : { enabled : true, secured : true, securityRule : { roles : "admin" } }, // Security headers securityHeaders : { enabled : true, trustUpstream : false, contentSecurityPolicy : { enabled : false, policy : "" }, contentTypeOptions : { enabled : true }, frameOptions : { enabled : true, value : "SAMEORIGIN" }, hsts : { enabled : true, "max-age" : "31536000", includeSubDomains : false, preload : false }, hostHeaderValidation : { enabled : false, allowedHosts : "" }, ipValidation : { enabled : false, allowedIPs : "" }, referrerPolicy : { enabled : true, policy : "same-origin" }, secureSSLRedirects : { enabled : false }, xssProtection : { enabled : true, mode : "block" } }, // JWT configuration jwt : { issuer : "https://myapp.com", secretKey : getSystemSetting( "JWT_SECRET", "" ), customAuthHeader : "x-auth-token", expiration : 60, enableRefreshTokens : true, refreshExpiration : 10080, customRefreshHeader : "x-refresh-token", enableAutoRefreshValidator : false, enableRefreshEndpoint : true, algorithm : "HS512", requiredClaims : [], tokenStorage : { enabled : true, keyPrefix : "cbjwt_", driver : "cachebox", properties : { cacheName : "default" } } }, // CSRF protection csrf : { enableAutoVerifier : false, verifyExcludes : [], rotationTimeout : 30, enableEndpoint : false, enableAuthTokenRotator : true } } }; ``` -------------------------------- ### Configure Security Interceptor with Database Rules Source: https://github.com/coldbox-modules/cbsecurity/wiki/DB-Properties Use these properties to define the database connection and table for security rules when `rulesSource` is set to 'db'. Ensure the `rulesDSN` and `rulesTable` are correctly specified. ```javascript interceptors = [ {class="cbsecurity.interceptors.Security", name="ApplicationSecurity", properties={ useRegex = true, rulesSource = "db", validatorModel = "SecurityService", rulesDSN = "myApp", rulesTable = "securityRules", rulesOrderBy = "order asc" }} ]; ``` -------------------------------- ### Module-Level Security Configuration Source: https://context7.com/coldbox-modules/cbsecurity/llms.txt Configure security settings for a specific ColdBox module, including firewall rules, validators, and event mappings for authentication and authorization. This allows for granular control over security per module. ```cfml // modules_app/api/ModuleConfig.cfc component { this.title = "API Module"; settings = { cbsecurity = { firewall : { // Module-specific validator validator : "JwtAuthValidator@cbsecurity", // Module-specific invalid events invalidAuthenticationEvent : "api:security.unauthorized", defaultAuthenticationAction : "override", invalidAuthorizationEvent : "api:security.forbidden", defaultAuthorizationAction : "override", // Module-specific rules rules : { inline : [ { secureList : "api:users\..*", match : "event", permissions : "api:users" }, { whitelist : "api:auth\.login,api:auth\.register", secureList : "api:.*", match : "event" } ] } } } }; } ``` -------------------------------- ### User Login and Token Generation Source: https://context7.com/coldbox-modules/cbsecurity/llms.txt Authenticate users by username and password, optionally including custom claims. Handles invalid credentials and returns access or refresh tokens. ```javascript // Authenticate and get tokens function login( event, rc, prc ) { try { // Returns access token (or struct with access/refresh tokens if enabled) var tokens = jwtAuth().attempt( username = rc.username, password = rc.password, customClaims = { "device" : rc.deviceId } ); // If refresh tokens enabled, returns struct // { access_token: "...", refresh_token: "..." } event.getResponse().setData( tokens ); } catch ( InvalidCredentials e ) { event.getResponse().setError( true ).setMessages( [ "Invalid credentials" ] ); } } ``` ```javascript // Generate tokens from authenticated user function generateTokens( event, rc, prc ) { var user = userService.get( rc.userId ); // Generate token for user var tokens = jwtAuth().fromUser( user = user, customClaims = { "type" : "api", "tenant" : user.getTenantId() }, refreshCustomClaims = { "refreshable" : true } ); return tokens; } ``` -------------------------------- ### Secure Execution for Same User with Custom Message Source: https://context7.com/coldbox-modules/cbsecurity/llms.txt Use `cbSecure().secureSameUser()` to ensure the operation is performed by the same user, with an option to provide a custom error message. ```javascript function changePassword( event, rc, prc ) { var targetUser = userService.get( rc.userId ); cbSecure().secureSameUser( user = targetUser, message = "You can only change your own password" ); } ``` -------------------------------- ### Conditional Execution Based on Permissions (None) Source: https://context7.com/coldbox-modules/cbsecurity/llms.txt Use `cbSecure().whenNone()` to execute a `success` callback only if the user does not possess any of the specified permissions. Permissions can be a comma-separated string or an array. ```javascript cbSecure().whenNone( permissions = "guest", success = ( user, permissions ) => { prc.showPremiumContent = true; } ); ``` -------------------------------- ### Inject and Use JWT Service Source: https://context7.com/coldbox-modules/cbsecurity/llms.txt Inject the JWT service directly or use the jwtAuth() mixin helper. This is the entry point for all JWT operations. ```javascript property name="jwtService" inject="jwtService@cbSecurity"; // Or use the mixin helper jwtAuth() ``` -------------------------------- ### Configure Module Firewall Rules in ModuleConfig.cfc Source: https://github.com/coldbox-modules/cbsecurity/blob/development/readme.md Define module-specific firewall settings, including custom validators, and append security rules to the global configuration. These rules can override global defaults for authentication and authorization events. ```javascript // module settings - stored in modules.name.settings settings = { // CB Security Rules to append to global rules cbsecurity = { firewall : { // Module Relocation when an invalid access is detected, instead of each rule declaring one. "invalidAuthenticationEvent" : "mod1:secure.index", // Default Authentication Action: override or redirect or block when a user has not logged in "defaultAuthenticationAction" : "override", // Module override event when an invalid access is detected, instead of each rule declaring one. "invalidAuthorizationEvent" : "mod1:secure.auth", // Default Authorization Action: override or redirect or block when a user does not have enough permissions to access something "defaultAuthorizationAction" : "override", // Custom validator for the module. "validator" : "JwtAuthValidator@cbsecurity" // You can define your security rules here or externally via a source "rules" : [ { "secureList" : "mod1:home" }, { "secureList" : "mod1/modOverride", "match" : "url", "action" : "override" } ] } } }; ``` -------------------------------- ### Basic CFLogin Structure Source: https://github.com/coldbox-modules/cbsecurity/wiki/Default-Security Use this basic structure for implementing ColdFusion's cflogin tag. Place your login logic within the cflogin block and use cfloginuser to log in the user with their credentials and roles. ```html Your login logic here <--- Log in the user with appropriate credentials ---> ``` -------------------------------- ### Configure CB Security Module Settings Source: https://github.com/coldbox-modules/cbsecurity/blob/development/readme.md Defines the module settings for CB Security and CB Auth, including user service class and authentication provider configurations. ```javascript moduleSettings = { cbauth = { // This is the path to your user object that contains the credential validation methods userServiceClass = "entities.user" }, cbsecurity = { /** * -------------------------------------------------------------------------- * Authentication Services * -------------------------------------------------------------------------- * Here you will configure which service is in charge of providing authentication for your application. * By default we leverage the cbauth module which expects you to connect it to a database via your own User Service. * * Available authentication providers: * - cbauth : Leverages your own UserService that determines authentication and user retrieval * - basicAuth : Leverages basic authentication and basic in-memory user registration in our configuration * - custom : Any other service that adheres to our IAuthService interface */ authentication : { // The WireBox ID of the authentication service to use which must adhere to the cbsecurity.interfaces.IAuthService interface. "provider" : "authenticationService@cbauth", // WireBox ID of the user service to use when leveraging user authentication, we default this to whatever is set // by cbauth or basic authentication. (Optional) "userService" : "", // The name of the variable to use to store an authenticated user in prc scope on all incoming authenticated requests "prcUserVariable" : "oCurrentUser" }, /** * -------------------------------------------------------------------------- * Basic Auth * -------------------------------------------------------------------------- * These settings are used so you can configure the hashing patterns of the user storage * included with cbsecurity. These are only used if you are using the `BasicAuthUserService` as * your service of choice alongside the `BasicAuthValidator` */ basicAuth : { // Hashing algorithm to use hashAlgorithm : "SHA-512", // Iterates the number of times the hash is computed to create a more computationally intensive hash. hashIterations : 5, // User storage: The `key` is the username. The value is the user credentials that can include // { roles: "", permissions : "", firstName : "", lastName : "", password : "" } users : {} }, /** * -------------------------------------------------------------------------- * CSRF - Cross Site Request Forgery Settings * -------------------------------------------------------------------------- * These settings configures the cbcsrf module. Look at the module configuration for more information */ csrf : { // By default we load up an interceptor that verifies all non-GET incoming requests against the token validations enableAutoVerifier : false, // A list of events to exclude from csrf verification, regex allowed: e.g. stripe\..* verifyExcludes : [], // By default, all csrf tokens have a life-span of 30 minutes. After 30 minutes, they expire and we aut-generate new ones. // If you do not want expiring tokens, then set this value to 0 rotationTimeout : 30, // Enable the /cbcsrf/generate endpoint to generate cbcsrf tokens for secured users. enableEndpoint : false, // The WireBox mapping to use for the CacheStorage cacheStorage : "CacheStorage@cbstorages", // Enable/Disable the cbAuth login/logout listener in order to rotate keys enableAuthTokenRotator : true }, /** * -------------------------------------------------------------------------- * Firewall Settings * -------------------------------------------------------------------------- * The firewall is used to block/check access on incoming requests via security rules or via annotation on handler actions. * Here you can configure the operation of the firewall and especially what Validator will be in charge of verifying authentication/authorization * during a matched request. */ firewall : { // Auto load the global security firewall automatically, else you can load it a-la-carte via the `Security` interceptor "autoLoadFirewall" : true, // The Global validator is an object that will validate the firewall rules and annotations and provide feedback on either authentication or authorization issues. "validator" : "AuthValidator@cbsecurity", // Activate handler/action based annotation security "handlerAnnotationSecurity" : true, // The global invalid authentication event or URI or URL to go if an invalid authentication occurs "invalidAuthenticationEvent" : "" ``` -------------------------------- ### Configure Securelist Events Source: https://github.com/coldbox-modules/cbsecurity/wiki/First-Rule-Analysis Use the `` element to define events that require security validation. These events will be secured unless they match a pattern in the whitelist. ```xml ^user\..*, ^admin ``` -------------------------------- ### Inline Security Rules Configuration Source: https://context7.com/coldbox-modules/cbsecurity/llms.txt Define security rules directly within the ColdBox.cfc file for event and URL access control. Supports regex matching for secure lists. ```js firewall : { rules : { useRegex : true, inline : [ // Secure admin area - requires admin role { secureList : "^admin\\..*", match : "event", roles : "admin", permissions : "", redirect : "security.login" }, // Secure API endpoints - requires authentication { secureList : "^api\\..*", match : "event", roles : "", permissions : "api:access", action : "block" }, // URL-based security with whitelist { whitelist : "api/v1/public.*", secureList : "api/v1/.*", match : "url", roles : "", permissions : "api:read", httpMethods : "GET,POST", allowedIPs : "*" }, // Override event on unauthorized { secureList : "^dashboard\\..*", match : "event", roles : "user,admin", overrideEvent : "security.unauthorized" } ] } } ``` -------------------------------- ### Check User Permissions (OR Logic) Source: https://context7.com/coldbox-modules/cbsecurity/llms.txt Use `cbSecure().has()` to check if a user possesses at least one of the specified permissions. Permissions can be provided as a comma-separated string or an array. ```javascript if ( cbSecure().has( "users:read" ) ) { // User has users:read permission } if ( cbSecure().has( "users:read,users:write" ) ) { // User has users:read OR users:write } if ( cbSecure().has( [ "admin", "superuser" ] ) ) { // User has admin OR superuser permission } ``` -------------------------------- ### External Security Rules Providers Source: https://context7.com/coldbox-modules/cbsecurity/llms.txt Load security rules from external sources like JSON, XML, a database, or a custom model. Configure the 'provider' block with the appropriate 'source' and 'properties'. ```js // JSON file provider firewall : { rules : { provider : { source : "config/security.json", properties : {} } } } ``` ```js // XML file provider firewall : { rules : { provider : { source : "config/security.xml", properties : {} } } } ``` ```js // Database provider firewall : { rules : { provider : { source : "db", properties : { dsn : "myDatasource", table : "securityRules", sql : "SELECT * FROM securityRules ORDER BY order ASC", orderBy : "order" } } } } ``` ```js // Model provider firewall : { rules : { provider : { source : "model", properties : { model : "SecurityRuleService", method : "getSecurityRules" } } } } ``` -------------------------------- ### Match Incoming Events Source: https://github.com/coldbox-modules/cbsecurity/wiki/First-Rule-Analysis Use the `` element to specify which incoming events the security rule should apply to. This acts as a filter for event processing. ```xml event ``` -------------------------------- ### Configure Security Interceptor with Model Rules Source: https://github.com/coldbox-modules/cbsecurity/wiki/Model-Properties Use this configuration to specify that security rules should be loaded from a model object. Ensure the `validatorModel` and `rulesModel` properties point to the correct model, and `rulesModelMethod` specifies the method that returns the rules query. ```javascript interceptors = [ {class="cbsecurity.interceptors.Security", name="ApplicationSecurity", properties={ useRegex = true, rulesSource = "model", validatorModel = "SecurityService", rulesModel = "SecurityService", rulesModelMethod = "getRules" }} ]; ``` -------------------------------- ### CBSecurity Service API - Authentication and User Management Source: https://context7.com/coldbox-modules/cbsecurity/llms.txt Programmatically manage user authentication, logout, and retrieve user information using the CBSecurity service. Requires injection or mixin usage. ```js // Inject the service property name="cbSecurity" inject="@cbsecurity"; // Or use the mixin helper cbSecure() // Check if user is logged in if ( cbSecure().isLoggedIn() ) { var currentUser = cbSecure().getUser(); } // Check if user is a guest (not logged in) if ( cbSecure().guest() ) { relocate( "security.login" ); } // Authenticate a user try { var user = cbSecure().authenticate( "username", "password" ); // User is now logged in } catch ( InvalidCredentials e ) { // Handle invalid credentials } // Logout the current user cbSecure().logout(); // Get the authentication service var authService = cbSecure().getAuthService(); // Get the user service var userService = cbSecure().getUserService(); ``` -------------------------------- ### Define Whitelisted Events Source: https://github.com/coldbox-modules/cbsecurity/wiki/First-Rule-Analysis The `` element allows you to specify events that should bypass security verification. Events matching these patterns will not be checked. ```xml user\.login,user\.logout,^main.* ``` -------------------------------- ### Set Redirect Event Source: https://github.com/coldbox-modules/cbsecurity/wiki/First-Rule-Analysis The `` element specifies the event to redirect to if security validation fails. This is used to relocate the user via `setNextEvent()`. ```xml user.login ```