# Introduction

## WELCOME TO THE COLDBOX SECURITY MODULE

This module will provide your application with a security rule engine.

### LICENSE Apache License, Version 2.0.

### IMPORTANT LINKS

* <https://www.forgebox.io/view/cbsecurity>

### SYSTEM REQUIREMENTS

* Lucee 4.5+
* ColdFusion 9+

## INSTRUCTIONS

Just drop into your **modules** folder or use CommandBox to install

`box install cbsecurity`

You will then need to configure the interceptor via the `cbsecurity` settings in your main `ColdBox.cfc` or you can also declare the interceptor manually by leveraging the class: `cbsecurity.interceptors.Security`. If you define the `cbsecurity` settings, then the module will load the interceptor automatically for you with those settings.

You can find all the documentation here: <https://github.com/ColdBox/cbox-security/wiki>

### Security Rules

Security rules can come from xml, json, query, memory or custom locations. You will find some examples in this module's `config` folder.

### Settings

Below are the security settings you can use for this module. Remember you must create the `cbsecurity` struct in your `ColdBox.cfc`:

```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"
}
```

### Manual Interceptor Declaration

Here is a sample declaration you can use in your `ColdBox.cfc`:

```javascript
// Security Interceptor declaration.
interceptors = [
    { class="cbsecurity.interceptors.Security",
      name="CBSecurity",
      properties={
        // please add the properties you want here to configure the security interceptor
        rulesFile = "/cbsecurity/config/security.json.cfm",
        rulesSource = "json"
     } }
];
```


# Overview

The topic of security is always an interesting and essential one. However, most MVC frameworks offer very loose security when it comes down to an event-oriented architecture. ColdBox Interceptors change this behavior as we have the ability to intercept requests in any point in time during our application executions. With this feature we introduce our Security Module that implements what we call **ColdBox Security**. With the ColdBox security module you will be able to secure all your public and private ColdBox events from execution and incoming URL patterns. However, as we all know, every application has different requirements and since we are keen on extensibility, the module can be configured to work with whatever security authentications and permissions you might have.

![](https://github.com/ColdBox/cbox-security/wiki/ColdBoxSecurity.jpg)

The module wraps itself around the `preProcess` execution of your request and also (if configured) on any \`runEvent()\`\` methods that get executed internally. The module is based on a custom rules engine that will validate a request against a set of rules that you define and then if a rule is matched, it will try to see if the user is authenticated and in a specific criteria (as specified by you). The two available authentication algorithms are the following:

1. (**default**) By using `cflogin, cfloginuser, cflogout`
2. Security Validation Object that you create and implement.

The default security is based on what ColdFusion gives you for basic security using their security tags. You basically use `cfloginuser` to log in a user and set their appropriate roles in the system. The module can then match to these roles via the security rules you have created.

The second method of authentication is based on your custom security logic. You will be able to register a validation object with the module. Once a rule is matched, the module will call your validation object, send in the rule and ask if the user can access it or not. It will be up to your logic to determine if the rule is satisfied or not.

### Features

* Secures incoming events and URIs
* If enabled, secure internal event executions via `preEvent()` interceptions
* Security rules can exist in:
  * XML File
  * JSON File
  * Database
  * Model/WireBox Object
  * IoC Module
  * ColdBox Cache (Placing a query of rules into the cache)
* The rules can be configured to use regular expressions or simple snippets
* Can use ColdFusion authentication security
* Can Use your own Security Validation by creating a security validation object.

### Resources

* `cflogin` - <http://help.adobe.com/en_US/ColdFusion/9.0/CFMLRef/WSc3ff6d0ea77859461172e0811cbec22c24-7db9.html>
* `cfloginuser` - <http://help.adobe.com/en_US/ColdFusion/9.0/CFMLRef/WSc3ff6d0ea77859461172e0811cbec22c24-7c5c.html>
* `cflogout` - <http://help.adobe.com/en_US/ColdFusion/9.0/CFMLRef/WSc3ff6d0ea77859461172e0811cbec22c24-7c5b.html>
* security tags - <http://help.adobe.com/en_US/ColdFusion/9.0/CFMLRef/WSc3ff6d0ea77859461172e0811cbec17576-7ffc.html#WSc3ff6d0ea77859461172e0811cbec22c24-7705>


# How It Works

The basics of the security validation is that you define a set of rules, much like how you define a firewall. Each rule is composed of several elements: **securelist**, **whitelist**, **roles**, **permissions**, **match**, and **redirect**. However, each rule can be expanded by the developer as needed with custom elements, etc. Each rule will be evaluated in the order that it is declared and the follow validation via our flow diagram below.

1. An incoming request or internal event reaches the first rule and the type of matching is determined: event or URI matching
2. The incoming event or URI is matched against the *whitelist* element
   1. If matched, then the event is whitelisted so it continues to the next rule
   2. Else, continue
3. The incoming event or URI is matched against the *securelist* element
   1. If not matched, then continue to next rule
   2. Else, continue validation
4. Do we have a custom validator or not?
   1. Yes, validate against the custom validator
   2. No, validate against ColdFusion's logged in user roles or logged in credentials
5. If validation fails, redirect the user via the *redirect* element


# Declaring the Interceptor

In order to enable ColdBox security you must register the Security interceptor in your parent or other module configuration's `interceptors` section:

```javascript
interceptors = [
    { 
        class       = "cbSecurity.interceptors.Security", 
        name        = "ApplicationSecurity", 
        properties  = {
            // Security properties go here.
        }
    }
];
```

{% hint style="info" %}
**IMPORTANT** If you are using SES or URL mappings in your ColdBox 4 application, make sure that you declare the security interceptor after the SES interceptor. Interceptors require order, so security needs for the URL to be translated first. In coldbox 5 SES is handled by the Routing service, so you don't need this SES interceptor.
{% endhint %}

## Global Properties

| Property           | Type    | Required | Default | Description                                                                                                                                                                                                                                                |
| ------------------ | ------- | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `useRegex`         | boolean | false    | true    | By default all secure and white lists are matched using regular expressions. You can disable it if you like and use plain old string matching.                                                                                                             |
| `queryChecks`      | boolean | false    | false   | Flag that tells the interceptor to validate the columns in the security rules. This makes sure all columns have the same columns. By default it is in relaxed mode so all columns are used.                                                                |
| `preEventSecurity` | boolean | false    | false   | This turns on the `preEvent`execution point that will make sure that before any event is fired internally, that its verified against the security rules. Only use this if you really want to secure all internal events, else this can hinder performance. |
| `ruleSource`       | string  | true     | ---     | Where to look for the rules as described above, this value has to be a choice from the following list `xml,json,db,model,ioc or ocm`.                                                                                                                      |
| `validator`        | string  | false    | ---     | The class path of the validator object to use. The interceptor will create the object for you and cache it internally. If the object has an `init()` method, the interceptor will call it for you.                                                         |
| `validatorModel`   | string  | false    | ---     | The model name of the security validator to use for custom validations. The interceptor will call `getModel()` with the name of this property to be retrieved via [WireBox](http://wirebox.ortusbooks.com/)                                                |
| `validatorIOC`     | string  | false    | ---     | The bean name of the security validator to use for custom validations. The interceptor will ask the IoC module for the bean according to this property                                                                                                     |


# XML Properties

The following are properties used when the source of the rules is xml

| Property    | Type   | Required                  | Default | Description                                 |
| ----------- | ------ | ------------------------- | ------- | ------------------------------------------- |
| `rulesfile` | string | true if rulesSource = xml | ---     | The location of the security rules xml file |

```javascript
interceptors = [
    {class="cbsecurity.interceptors.Security", name="ApplicationSecurity", properties={
        useRegex = true, rulesSource = "xml", validatorModel = "SecurityService",
        rulesFile = "config/security.xml.cfm"
    }}
];
```


# JSON Properties

The following are properties used when the source of the rules is json

| Property    | Type   | Required                   | Default | Description                                  |
| ----------- | ------ | -------------------------- | ------- | -------------------------------------------- |
| `rulesfile` | string | true if rulesSource = JSON | ---     | The location of the security rules json file |

```javascript
interceptors = [
    {class="cbsecurity.interceptors.Security", name="ApplicationSecurity", properties={
        useRegex = true, rulesSource = "json", validatorModel = "SecurityService",
        rulesFile = "config/security.json.cfm"
    }}
];
```

<br>


# DB Properties

The following are properties used when the source of the rules is db or coming from the database.

| Property       | Type   | Required                 | Default                   | Description                                                                                                                                                   |
| -------------- | ------ | ------------------------ | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `rulesDSN`     | string | true if rulesSource = db | ---                       | The dsn to use if the rules are coming from a database                                                                                                        |
| `rulesTable`   | string | true if rulesSource = db | ---                       | The table where the rules are                                                                                                                                 |
| `rulesSQL`     | string | false                    | `select* from rulesTable` | The custom SQL statement to use to retrieve the rules according to the rulesTable property. If not set, the default of select\* from rulesTable will be used. |
| `rulesOrderBy` | string | false                    | ---                       | The column to order the rules by. If not chosen, the interceptor will not order the query, just select it.                                                    |

```javascript
interceptors = [
    {class="cbsecurity.interceptors.Security", name="ApplicationSecurity", properties={
        useRegex = true, rulesSource = "db", validatorModel = "SecurityService",
        rulesDSN = "myApp", rulesTable = "securityRules", rulesOrderBy = "order asc"
    }}
];
```


# IOC Properties

The following are properties used when the source of the rules is ioc or coming from an IoC module

| Property          | Type   | Required                  | Default | Description                                                                                                                                           |
| ----------------- | ------ | ------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| `rulesBean`       | string | true if rulesSource = ioc | ---     | The bean name to ask the IoC module for that has the rules                                                                                            |
| `rulesBeanMethod` | string | true if rulesSource = ioc | ---     | The method in the bean to call that will return a query of rules                                                                                      |
| `rulesBeanArgs`   | string | false                     | ---     | A comma-delimited list of arguments to send into the method. This is an optional argument and if not set, the method will be called with no arguments |

```javascript
interceptors = [
    {class="cbsecurity.interceptors.Security", name="ApplicationSecurity", properties={
        useRegex = true, rulesSource = "ioc", validatorModel = "SecurityService",
        rulesBean = "SecurityService", rulesBeanMethod = "getRules", rulesBeanArgs = "sorting=true"
    }}
];
```


# OCM Properties

The following are properties used when the source of the rules is `ocm` or coming from the CacheBox

| Property      | Type   | Required | Default | Description                                                                        |
| ------------- | ------ | -------- | ------- | ---------------------------------------------------------------------------------- |
| `rulesOCMKey` | string | true     | ---     | The cache key to use to retrieve the rules from the ColdBox default cache provider |

```javascript
interceptors = [
    {class="cbsecurity.interceptors.Security", name="ApplicationSecurity", properties={
        useRegex = true, rulesSource = "ocm", validatorModel = "SecurityService",
        rulesOCMKey = "qSecurityRules"
    }}
];
```


# Security Rules

Now that we have seen all the properties of this module, how to configure it and declare it, let's look at how the rules work. All the security rules follows the following format, however, you can append as many columns as you like for your own custom validations and the interceptor will register all the columns you pass to it:

| Property      | Type         | Description                                                                                                       |
| ------------- | ------------ | ----------------------------------------------------------------------------------------------------------------- |
| `match`       | event or URI | Determines if it needs to match the incoming URI or the incoming event. By default it matches the incoming event. |
| `whitelist`   | varchar      | A comma delimited list of events or patterns to whitelist or to bypass security on                                |
| `securelist`  | varchar      | A comma delimited list of events or patterns to secure                                                            |
| `roles`       | varchar      | A comma delimited list of roles that can access these secure events                                               |
| `permissions` | varchar      | A comma delimited list of permissions that can access these secure events                                         |
| `redirect`    | varchar      | An event or route to redirect if the user is not in a role or permission                                          |

You might be asking, why is the element permissions here, if the default ColdFusion security doesn't work with permissions but with roles. Well, in anticipation to customizations and permissions based systems, the permissions element exists. It's there already if you need to use it. However, the default interceptor security does not use it, just the roles element. A few guidelines:

* Test your regular expressions (<http://gskinner.com/blog/archives/2008/03/regexr_free_onl.html>)
* Determine if you want to secure the incoming URL or event
* Order of declaration of the rules is important as they are fired in order
* Test your `whitelist` events, if not you might be producing endless loops of security redirections
* Make sure implicit events are whitelisted if you are securing the entire application events
* As best practice, create your own validator object for more granular control

> **IMPORTANT** The basic rules table is provided. However, it is very denormalized and for simple applications. If your applications will deal with many permissions and roles, I suggest you build your DB according to your business rules and then just create a method that can join the rules into the above format. You can easily do this in SQL or create a view for your security rules. If you are doing this, then your security implementations are advanced and you know what you are doing (Hopefully). So please note that the way you store the rules in the DB is your priority and consideration.


# Sample JSON Rules

```javascript
[
    {
        "whitelist": "user\\.login,user\\.logout,^main.*",
        "securelist": "^user\\.*, ^admin",
        "match": "event",
        "roles": "admin",
        "permissions": "",
        "redirect": "user.login",
        "useSSL": false
    },
    {
        "whitelist": "",
        "securelist": "^shopping",
        "match": "url",
        "roles": "",
        "permissions": "shop,checkout",
        "redirect": "user.login",
        "useSSL": true
    }
]
```


# Sample XML Rules

```markup
<?xml version="1.0" encoding="ISO-8859-1"?>
<-- <
Declare as many rule elements as you want, order is important 
Remember that the securelist can contain a list of regular
expressions if you want

ex: All events in the user handler
 user\..*
ex: All events
 .*
ex: All events that start with admin
 ^admin

If you are not using regular expressions, just write the text
that can be found in an event.
-->
<rules>
    <rule>
        <match>event</match>
        <whitelist>user\.login,user\.logout,^main.*</whitelist>
        <securelist>^user\..*, ^admin</securelist>
        <roles>admin</roles>
        <permissions>read,write</permissions>
        <redirect>user.login</redirect>
    </rule>

    <rule>
           <match>event</match>
        <whitelist></whitelist>
        <securelist>^moderator</securelist>
        <roles>admin,moderator</roles>
        <permissions>read</permissions>
        <redirect>user.login</redirect>
    </rule>

    <rule>
           <match>url</match>
        <whitelist></whitelist>
        <securelist>/secured.*</securelist>
        <roles>admin,paid_subscriber</roles>
        <permissions></permissions>
        <redirect>user.pay</redirect>
    </rule>
</rules>
```

> **IMPORTANT** Please remember to white list your main events (implicit), login and logout events if you will be securing the entire application.

## First Rule Analysis

As you can see from the sample, the first rule has the following elements

```
<match>event</match>
```

So it will match the incoming event.

```
<whitelist>user\.login,user\.logout,^main.*</whitelist>
```

This means that the following events will not be verified for security: user.login, user.logout and any event that starts with main will be let through, if they match the secure list pattern.

```
<securelist>^user\..*, ^admin</securelist>
```

This means that any event that starts with the word user will be secured and anything that starts with the word admin will also be secured, unless the incoming event matches a pattern in the whitelist element.

```
<roles>admin</roles>
```

This means that only a user with admin role will be allowed to visit the securelist events.

```
<permissions>read,write</permissions>
```

This probably means that I am doing my own security validation and apart from having the user have a role of admin, he/she must also have the read and write permissions. My own validator will validate this logic.

```
<redirect>user.login</redirect>
```

Then if it does not validate it will use this redirect element to relocate via `setNextEvent()`

## Second Rule Analysis

The second rule has the following elements:

```
<match>event</match>
```

So it will match the incoming event.

```
<whitelist></whitelist>
```

No white listed events are defined.

```
<securelist>^moderator</securelist>
```

This means that any event that starts with the word moderator will be secured and validated against the user's credentials.

```
<roles>admin,moderator</roles>
```

This means that users with roles of admin and moderator can execute events that are in the securelist.

```
<permissions>read</permissions>
```

This probably means that I am doing my own security validation and apart from having the user have a role of admin or moderator, he/she must also have the read permission. My own validator will validate this logic.

```
<redirect>user.login</redirect>
```

Then if it does not validate it will use this redirect element to relocate via `setNextEvent()`

## Third Rule Analysis

The third rule has the following elements:

```
<match>URL</match>
```

So it will match the incoming URL pattern after the domain name and application location.

```
<whitelist></whitelist>
```

No white listed events are defined.

```
<securelist>/secured.*</securelist>
```

It will secure any incoming URI that starts with /secured

```
<roles>admin,paid_subscriber</roles>
```

This means that users with roles of admin and paid\_subscriber can visit URLs with /secured in them

```
<permissions></permissions>
```

No permissions

```
<redirect>user.pay</redirect>
```

Then if it does not validate it will use this redirect element to relocate via `setNextEvent()`


# \_securedURL key

When the security module is about to relocate *redirect* element, it will save the incoming URL that was requested in a flash RAM variable called: `_securedURL`. This key will be persisted in the flash memory of the framework and when the user get's relocated to the `redirect` element, this key will exist in the request collection. You can then use this to store where they came from and do proper redirections. So always remember to use this key if you want to provide a seamless login experience to your users. You can easily place it in the login form:

```markup
#html.startForm(action=prc.xehDoLogin,name="loginForm",novalidate="novalidate")#
    <---< Secured URL --->
    #html.hiddenField(name="_securedURL",value=event.getValue('_securedURL',''))#

    #html.textfield(name="username",label="Username: ",size="40",required="required",class="textfield",value=prc.rememberMe)#
    #html.passwordField(name="password",label="Password: ",size="40",required="required",class="textfield")#
    
    <div id="loginButtonbar">
    #html.checkBox(name="rememberMe",value=true,checked=(len(prc.rememberMe)))# 
    #html.label(field="rememberMe",content="Remember Me  ",class="inline")#
    #html.submitButton(value="  Log In  ",class="buttonred")#
    </div>
    
    <br/>
    <img src="#prc.cbRoot#/includes/images/lock.png" alt="lostPassword" />
    <a href="#event.buildLink(prc.xehLostPassword)#">Lost your password?</a> 
    
#html.endForm()#
```


# Default Security

This module will try to use ColdFusion's `cflogin + cfloginuser`authentication by default. However, if you are using your own authentication mechanisms you can still use this module by implementing a Security Validator Object (See next section). Below we can see a sample on how to use the `cflogin` tag:

Example:

```
<cflogin>
    
    Your login logic here
    
    <---  Log in the user with appropriate credentials --->
    <cfloginuser name="name" password="password" roles="ROLES HERE">
</cflogin>

<---  Some Real sample --->
<cflogin>
    <cfif getUserService().authenticate(rc.username,rc.password)>
        <cfloginuser name="#rc.username#" password="#rc.password#" roles="#getUserService().getRoles(rc.username)#" />
    </cfif>
</cflogin>
```

For more information about `cflogin, cfloginuser and cflogout`, please visit the docs <http://cfdocs.org/security-functions>


# Custom Security Validator Object

A security validator object is a simple CFC that implements the following function:

```
boolean userValidator( rule:struct, controller:coldbox.system.web.Controller )
```

This function must return a `boolean` variable and it must validate a user according to the rule that just ran by testing the fields that get sent in as a rule. Where this method exists is up to you. It will also receive a reference to the current ColdBox controller. You can use the controller to call other plugins, persist keys, or anything you like (please see the controller API). The important note here is that the rule structure contains all the elements/columns you defined in your xml or query. Below is a real life example:

```
<!---  User Validator for security --->
<cffunction name="userValidator" access="public" returntype="boolean" output="false" hint="Verifies that the user is in any permission">
    <!---************************************************************** --->
    <cfargument name="rule"     required="true" type="struct"   hint="The rule to verify">
    <cfargument name="controller" type="any" required="true" hint="The coldbox controller" />
    <!---************************************************************** --->
    <!---  Local call to get the user object from the session --->
    <cfset var oUser = getUserSession()>
    <!---  The results boolean variable I will return --->
    <cfset var results = false>
    <!---  The permission I am checkin --->
    <cfset var thisPermission = "">
            
    <!---  Authorized Check, if true, then see if user is valid. This column is an additional column in my query --->
    <cfif arguments.rule['authorize_check'] and oUser.getisAuthorized()>
        <!---  I first check if the user is authorized or not if set in the db rules --->
        <cfset results = true>
    </cfif>
    
    <!---  Loop Over Permissions to see if my user is in any of them. --->
    <cfloop list="#arguments.rule['permissions']#" index="thisPermission">
    
        <!---  My user object has a method called check permission that I call with a permission to validate --->
        <cfif oUser.checkPermission( thisPermission ) >
            <!---  This permission existed, I only need one to match as per my business logic, so let's return and move on --->
            <cfset results = true>
            <cfbreak>
        </cfif>
    </cfloop>
    
    <!---  I now return whether the user can view the incoming rule or not --->
    <cfreturn results>
</cffunction>
```

Or, in `cfscript`:

```javascript
/** 
 * 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;
}
```


# Introduction

The ColdBox `cbsecurity` module is a collection of modules to help secure your applications.

The major areas of concern are:

* A **security authentication/authorization firewall** ( `cbsecurity` ) which can secure your application based on:
  * Security rules and a rule engine for validation incoming events or URL's
  * Handler annotations
* A **security service** for explicit authorizations ( `cbsecurity` ) to provide you with functional approaches to security context authorization in **any** layer of your application.
* A **JWT generator, decoder and authentication services** ( `jwtcfml` )&#x20;
* Cross Site Request Forgery **(CSRF) Protection** ( `cbcsrf` )
* An **authentication manage**r ( `cbauth` )

## Module composition

![Cbsecurity consumes several other modules and leverages cbstorages for storage.](/files/-M8b8oOojXTh0tHlXruT)

## Features

* Ability to have global security rules
* Ability for modules to add their own security rules and action overrides
* Ability to distinguish between authentication and authorization issues
* Annotation driven cascading security for handlers and actions
* A functional security service that can be injected anywhere to provide you with authorizations
* Security rules can exist in:
  * XML File
  * JSON File
  * Database
  * Models
* The rules can be configured to use regular expressions or simple snippets
* Can use ColdFusion authentication security
* Can leverage any custom authentication provider
* Plug any Authentication service or can leverage [cbauth](https://github.com/elpete/cbauth) by default
* Capability to distinguish between invalid **authentication** and invalid **authorization** and determine an outcome of the process. &#x20;
* Ability to load/unload security rules from contributing modules.
* Ability for each module to define it's own `validator`
* JWT Access and Refresh Tokens Native support

## Versioning <a href="#versioning" id="versioning"></a>

The ColdBox Security Module is maintained under the [Semantic Versioning](http://semver.org/) guidelines as much as possible. Releases will be numbered with the following format:

```
<major>.<minor>.<patch>
```

And constructed with the following guidelines:

* Breaking backward compatibility bumps the major (and resets the minor and patch)
* New additions without breaking backward compatibility bumps the minor (and resets the patch)
* Bug fixes and misc changes bumps the patch

## License <a href="#license" id="license"></a>

Apache 2 License: [http://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)​

## Important Links <a href="#important-links" id="important-links"></a>

* Code: <https://github.com/coldbox-modules/cbsecurity>​
* Issues: <https://github.com/coldbox-modules/cbsecurity/issues>

## Professional Open Source <a href="#professional-open-source" id="professional-open-source"></a>

![Ortus Solutions, Corp](https://blobscdn.gitbook.com/v0/b/gitbook-28427.appspot.com/o/assets%2F-LA-UVvG0NM7NpDzssBL%2F-LA-Uaei0WzTH7Su5CR7%2F-LA-UqN1BRXynZ7RUVO7%2Fortussolutions_button.png?generation=1523647999385555\&alt=media)

The ColdBox Security Module is a professional open source software backed by [Ortus Solutions, Corp](http://www.ortussolutions.com/services) offering services like:

* Custom Development
* Professional Support & Mentoring
* Training
* Server Tuning
* Security Hardening
* Code Reviews
* [Much More](http://www.ortussolutions.com/services)

### Discussion & Help

The Box products and modules community for discussion and help can be found here:

[https://community.ortussolutions.com/c/box-modules/cbsecurity/](https://community.ortussolutions.com/c/box-modules/cbsecurity/26)

### HONOR GOES TO GOD ABOVE ALL <a href="#honor-goes-to-god-above-all" id="honor-goes-to-god-above-all"></a>

Because of His grace, this project exists. If you don't like this, then don't read it, it's not for you.

> "Therefore being justified by **faith**, we have peace with God through our Lord Jesus Christ: By whom also we have access by **faith** into this **grace** wherein we stand, and rejoice in hope of the glory of God." Romans 5:5


# Release History

In this section you will find the release notes for each version we release under this major version.  If you are looking for the release notes of previous major versions use the version switcher at the top left of this documentation book.  Here is a breakdown of our major version releases.

## Version 2.0

Version 2 is a major release of our security module.  We completely refactored the engine to make it more modern and to adhere to our new coding standards.  We then proceeded to enhance it to tap into our HMVC approach and allow rules to be contributed from modules themselves. We also added annotation driven security to complete the ability to secure not only incoming requests by rules but also by easy annotations.

We have made great strides in this release to make it a one-stop-shop for security concerns within ColdBox applications.

## Version 1.0

Our first release as a module decoupled from the ColdBox 2 days!


# What's New With 2.15.0

2021-DEC-10

### 🚀 Added

* Pass custom claims from `refreshToken()` method when refreshing tokens

In the JWTService the `refreshToken( struct customClaims = {} )` now has a `customClaims` argument which you can use to seed the refresh token with custom claims.

* Pass in the current JWT payload in to `getJWTCustomClaims( payload )` method

This was done to help authors have the exact payload that was used for the execution call. This affects the `IJwtSubject` interface.

* The auto refresh token features now will auto refresh not only on expired tokens, but on invalid and missing tokens as well. Thanks to @elpete

### 🐛 Fixed

* Timeout in token storage is now the token timeout


# What's New With 2.14.0

2021-OCT-07

### Added

* `threadsafe` annotation to all models to prevent invalid creations under load, since we don't use circular dependencies.


# What's New With 2.13.0

2021-SEP-

### Added

* Adobe 2021 Support
* Migration to GitHub Actions from Travis CI
* Refresh tokens support
* Refresh token endpoint `/cbsecurity/refreshToken` for secure refresh token generation
* Manual refresh token method on the `JwtService` : `refreshToken( token )`
* Auto refresh token header interceptions for JWT validators
* Detect on `authenticate()` if the payload is empty and throw the appropriate exceptions
* Added ability for the `authenticate( payload )` to receive a payload to authenticate
* Added ability to recreate the token storage using a `force` argument `getTokenStorage( force = false )`
* Ability for the `parseToken()` to choose to store and authenticate or just parse

### Fixed

* Unique `jti` could have collisions if tokens created at the same time, add randomness to it
* `TokenExpirationException` not relayed from the base jwt library
* If `variables.settings.jwt.tokenStorage.enabled` is disabled all invalidations failed, make sure if the storage is disabled to not throw storage exceptions.


# What's New With 2.12.0

2021-MAR-29

#### Added

* More and more apps will need real ip's from request, so expose it via the `CBSecurity` model service as : `getRealIp()`

#### Fixed

* When using `getHTTPREquestData()` send `false` so we DON'T retrieve the http body when we just need the headers
* More updates to `getRealIp()` when dealing with lists


# What's New With 2.11.x

2021-MAR-10

### Added

* Add a `secureSameUser` method to throw when passed a different user #29 (<https://github.com/coldbox-modules/cbsecurity/pull/29>)

## \[2.11.1] => 2021-MAR-10

### Fixed

* Fix `getRealIP()` to only return originating user's source IP, if the forwarded ip is a list


# What's New With 2.10.0

2021-FEB-12

#### Added

* Moved the registration of the validator from the `configure()` to the `afterAspectsLoad()` interception point to allow for modules to declare the validator if needed.
* Moved handler bean to `afterAspectsLoad()` to allow for module based invalid events to work.


# What's New With 2.9.0

2020-DEC-11

#### Fixed

* Fixes a typo in the `cbSecurity_onInvalidAuthorization` interception point declaration. Previously, the typo would prevent ColdBox from allowing the correctly-typed interception point from ever triggering an interception listener.
* The `userValidator()` method has been changed to `roleValidator()`, but the error message was forgotten! So the developer is told they need a `userValidator()` method... because the `userValidator` method is no longer supported. :/

#### Added

* The `isLoggedIn()` method now makes sure that a jwt is in place and valid, before determining if you are logged in or not.
* Migrated all automated tests to `focal` and `mysql8` in preparation for latest updates
* Add support for JSON/XML/model rules source when loading rules from modules.  Each module can now load rules not only inline but from the documented external sources.
* Ensure non-configured `rules` default to empty array


# What's New With 2.8.0

2020-NOV-09

#### Added

* `parseToken( token )` now accepts a token of your choice to work with in the request or it will continue to discover it if not passed.
* Added new JWT Service method: `invalidateAll()` which invalidates all tokens in the token storage
* Added the new event: `cbSecurity_onJWTInvalidateAllTokens` that fires once all tokens in the storage are cleared
* Added storage of the authenticated user into the `prc` scope when using `attempt()` to be consistent with API calls

#### Fixed

* Spelling corrections on the readme
* Added full var scoping for `cbsecurity` in JWTService calls


# What's New With 2.7.0

2020-SEP-14

#### Added

* Contributed module rules are now **pre-pended** instead of appended. (@wpdebruin)

#### Fixed

* Not loading rules by source file detection due to invalid setting check
* Don't trigger ColdBox's invalid event looping protection. It also auto-senses between ColdBox 6 and 5 (@homestar9)
* Fixed token scopes according to JWT spec, it is called `scope` and it is a **space** separated list. This doesn't change the User interface for it. (@wpdebruin)
* Update token storages so no token rejection anymore when storage is not enabled. (@wpdebruin)


# What's New With 2.6.0

2020-JUL-22

#### Added

* New build layout based on new module layout
* Auto github publishing release notes
* More formatting goodness and watcher

#### Fixed

* JWT Validator now passing `permissions` instead of `roles`
* Token Storage checking was being done even if disabled


# What's New With 2.5.0

2020-APR-03

In this release we have updated our internal authentication library `cbauth` to version 5.x.  Which brings the following changes to `cbauth`:

* Added preLogin, postLogin, preLogout, postLogout interception points
* `authentication()` now returns the user if valid

Just run `update cbsecurity` and you are done!


# What's New With 2.4.0

2020-APR-02

This release adds the inclusion of the Cross Site Request Forgery module into cbsecurity: `cbcsrf`.  You can find all the details about this module here: <https://github.com/coldbox-modules/cbcsrf>.  Below are the major features of this module:

### Features

* Ability to generate security tokens based on your session
* Automatic token rotation when leveraging `cbauth` login and logout operations
* Ability to on-demand rotate all security tokens for specific users
* Leverages `cbStorages` to store your tokens in CacheBox, which can be easily distributed and clustered
* Ability to create multiple tokens via unique reference `keys`
* Auto-verification interceptor that will verify all non-GET operations to ensure a security token is passed via `rc` or headers
* Auto-sensing of integration testing so the verifier can allow testing calls
* Token automatic rotation on specific time periods for enhance security
* Helpers to automatically generate hidden fields for the token
* Automatic generation endpoint that can be used for Ajax applications to request tokens for users


# What's New With 2.3.0

2020-MAR-30

This release focuses on bringing a strong focus on protecting every development layer of a ColdBox application. It introduces the `cbSecurity` model that can be used by any layer and provides you with a great functional API to secure your code.

## Explicit Authorizations

There will be times where you will need authorization checks outside of the incoming request rules or the handler annotations. This can be from within interceptors, models, layouts or even views. For this, we have provided the `cbSecurity` model so you can do explicit authorization checks anywhere you like.

## `cbSecurity` Model

You can inject our model or you can use our handy `cbsecure()` mixin (interceptors/handlers/layouts/views) and then call the appropriate security functions:

```javascript
// Mixin: Handlers/Interceptors/Layouts/Views
cbsecure()

// Injection
property name="cbSecurity" inject="@cbSecurity"
```

{% hint style="danger" %}
All security methods will call the application's configured Authentication Service to retrieve the currently logged in user. If the user is not logged in an immediate `NoUserLoggedIn` exception will be thrown by all methods.
{% endhint %}

### The `secure()` Methods

Now that you have access to the model, you can use the following method to verify explicit permissions and authorize access. This method will **throw an exception** if the user does not validate the incoming permissions context (`NotAuthorized`).

```javascript
// Verify the currently logged in user has those permission, 
// else throw a NotAuthorized exception
cbSecurity.secure( permissions, [message] );
cbsecure().secure( permissions, [message] );
```

* The `permission` can be an array, string or list of the permissions to validate.
* The `message` is a custom error message to be used in the `message` string of the exception thrown.

You also have two more authorization methods that will verify certain permission conditions for you:

```javascript
// Authorize that the user has ALL of the incoming permissions
cbSecurity.secureAll( permissions, [message] );
// Authorize that the user has NONE of the incoming permissions
cbSecurity.secureNone( permissions, [message] );
```

### Conditional Authorizations Using `when()`

There are also cases where you want to execute a piece of code by determining if the user has access to do so. For example, only a `USER_ADMIN` can change people's roles or you want to filter some data for certain users. For this, we have created the `when()` method with the following signature:

```javascript
when( permissions, success, fail )
```

* The `permissions` is a permission array or list that will be Or'ed&#x20;
* The `success` is a closure/lambda or UDF that will execute if the permissions validate. &#x20;
* The `fail` is a closure/lambda or UDF that will execute if the permissions DID not validate, much like an else statement

Both closures/functions takes in a `user` which is the currently authenticated user, the called in `permissions` and can return anything.

```javascript
// Lambda approach
( user, permissions ) => { 
    // your code here
};
// UDF/Closure
function( user, permissions ){ 
    // your code here
}
```

You can also chain the `when()` calls if needed, to create beautiful security contexts. So if we go back to our admin examples, we can do something like this:

```javascript
var oAuthor = authorService.getOrFail( rc.authorId );
prc.data = userService.getData();

// Run Security Contexts
cbSecure()
    // Only user admin can change to the incoming role
    .when( "USER_ADMIN", ( user ) => oAuthor.setRole( roleService.get( rc.roleID ) ) )
    // The system admin can set a super admin
    .when( "SYSTEM_ADMIN", ( user ) => oAuthor.setRole( roleService.getSystemAdmin() ) )
    // Filter the data to be shown to the user
    .when( "USER_READ_ONLY", ( user ) => prc.data.filter( ( i ) => !i.isClassified ) )

// Calling with a fail closure
cbSecurity.when(
    "USER_ADMIN",
    ( user ) => user.setRole( "admin" ), //success
    ( user ) => relocate( "Invaliduser" ) //fail
);
```

We have also added the following `whenX()` methods to serve your needs when evaluating the permissions:

```javascript
// When all permissions must exist in the user
whenAll( permissions, success, fail)
// When none of the permissions exist in the user
whenNone( permissions, success, fail )
```

### Verification Methods

If you just want to validate if a user has certain permissions or maybe no permissions at all or if a passed user is the same as the logged in user, then you can use the following boolean methods that only do verification.

{% hint style="success" %}
Please note that you could potentially do these type of methods by leveraging the currently logged in user and it's `hasPermission()` method. However, these methods provide abstraction and can easily be mocked!
{% endhint %}

```javascript
// Checks the user has one or at least one permission if the 
// permission is a list or array
boolean cbSecurity.has( permission );
// The user must have ALL the permissions
boolean cbSecurity.all( permission );
// The user must NOT have any of the permissions
boolean cbSecurity.none( permission );
// Verify if the passed in user is the same as the logged in user
boolean cbSecurity.sameUser( user );
```

These are great to have a unified and abstracted way to verifying permissions or if the passed user is the same as the logged in user. Here are some examples:

**View Layer**

```markup
<cfif cbsecure().has( "USER_ADMIN" )>
    This is only visible to user admins!
</cfif>

<cfif cbsecure().has( "SYSTEM_ADMIN" )>
    <a href="/user/impersonate/#prc.user.getId()#">Impersonate User</a>
</cfif>

<cfif cbsecure().sameUser( prc.user )>
    <i class="fa fa-star">This is You!</i>
</cfif>
```

Other Layers:

```javascript
if( cbSecurity.has( "PERM" ) ){
    auditUser();
}

if( cbSecurity.sameUser( prc.incomingUser ) ){
    // you can change your gravatar
}
```

{% hint style="info" %}
Please note that we do user equality by calling the `getId()` method of the authenticated user and the incoming user. This is part of our `IAuthUser` interface requirements.
{% endhint %}

### Authorization Contexts

There are also times where you need to validate custom conditions and block access to certain areas. This way, you can implement your own custom security logic and leverage **cbSecurity** for blockage. You will accomplish this via the `secureWhen()` method:

```javascript
secureWhen( context, [errorMessage] )
```

The `context` can be a closure/lambda/udf or a boolean evaluation:

```javascript
// Using as a closure/lambda
cbSecurity.secureWhen( ( user ) => !user.isConfirmed() )
cbSecurity.secureWhen( ( user ) => !oEntry.canPublish( user ) )

// Using a boolean evaluation
cbSecurity.secureWhen( cbSecurity.none( "AUTHOR_ADMIN" ) && !cbSecurity.sameUser( oAuthor )  )
cbSecurity.whenNone( "AUTHOR_ADMIN", ( user ) => relocate() );
```

The closure/udf will receive the currently authenticated user as the first argument.

```javascript
( user ) => {}
function( user );
```

### Securing Views

You can also use our handy `event.secureView()` method in the request context to pivot between views according to user permissions.

{% hint style="info" %}
cbSecurity injects the `secureView()` method into the request context via the `preProcess` interception point.
{% endhint %}

```javascript
event.secureView( permissions, successView, failView )
```

This will allow you to set the `successView` if the user has the permissions or the `failView` if they don't.

## `cbSecurity` Method Summary

### **Blocking Methods**

When certain permission context is met, if not throws `NotAuthorized`

* `secure( permissions, [message] )`
* `secureAll( permissions, [message] )`
* `secureNone( permissions, [message] )`
* `secureWhen( context, [message] )`
* `guard() alias to secure()`

### **Action Context Methods**

When certain permission context is met, execute the success function/closure, else if a `fail` closure is defined, execute that instead.

* `when( permissions, success, fail )`
* `whenAll( permissions, success, fail )`
* `whenNone( permissions, success, fail )`

### **Verification Methods**

Verify permissions or user equality

* `has( permissions ):boolean`
* `all( permissions ):boolean`
* `none( permissions ):boolean`
* `sameUser( user ):boolean`

### **Request Context Methods**

* `secureView( permissions, successView, failView )`


# What's New With 2.2.0

2020-FEB-12

## Features

* `Feature` : Migrated from the jwt to the `jwtcfml` (<https://forgebox.io/view/jwt-cfml>) library to expand encoding/decoding capabilities to support `RS` and `ES` algorithms:
  * HS256
  * HS384
  * HS512
  * RS256
  * RS384
  * RS512
  * ES256
  * ES384
  * ES512
* `Feature` : Added a new convenience method on the JWT Service: `isTokenInStorage( token )` to verify if a token still exists in the token storage
* `Feature` : If no jwt secret is given in the settings, we will dynamically generate one that will last for the duration of the application scope.
* `Feature` : New setting for `jwt` struct: `issuer`, you can now set the issuer of tokens string or if not set, then cbSecurity will use the home page URI as the issuer of authority string.
* `Feature` : All tokens will be validated that the same `iss` (Issuer) has granted the token

## Improvements

* `Improve` : Ability to have defaults for all JWT settings instead of always typing them in the configs
* `Improve` : More formattting goodness!

## Bugs

* `Bug` : Invalidation of tokens was not happening due to not using the actual key for the storage


# What's New With 2.1.0

2019-OCT-02

Small but big release!

* `Feature` : cbauth upgraded to version 4


# What's New With 2.0.0

2019-SEP-25

## New Features

* Adobe 2016,2018 Support
* Settings transferred to ColdBox 4/5 `moduleSettings` approach instead of root approach (See compat section)
* The `rulesModelMethod` now defaults to `getSecurityRules()`
* ColdFusion security validator has an identity now `CFValidator@cbsecurity` instead of always being inline.
* You can now add an `overrideEvent` element to a rule. If that is set, then we will override the incoming event via `event.overrideEvent()` instead of doing a relocation using the `redirect` rule element.
* You can now declare your rules inline in the configuration settings using the `rules` key. This will allow you to build the rules in your config instead of a rule source.
* We now can distinguish between invalid auth and invalid authorizations
* New interception block points `cbSecurity_onInvalidAuthentication`, `cbSecurity_onInvalidAuhtorization`
* You now have a `defaultAuthorizationAction` setting which defaults to `redirect`
* You now have a `invalidAuthenticationEvent` setting that can be used
* You now have a `defaultAuthenticationAction` setting which defaults to `redirect`
* You now have a `invalidAuthorizationEvent` setting that can be used
* If a rule is matched, we will store it in the `prc` as `cbSecurity_matchedRule` so you can see which security rule was used for processing invalid access actions.
* If a rule is matched we will store the validator results in `prc` as `cbSecurity_validatorResults`
* Ability for modules to register cbSecurity rules and setting overrides by registering a `settings.cbSecurity` key.
* New security rule visualizer for graphically seeing you rules and configuration.  Can be locked down via the `enableSecurityVisualizer` setting. Disabled by default.
* Annotation based security for handlers and actions using the `secured` annotation.  Which can be boolean or a list of permissions, roles or whatever you like.
* You can disable annotation based security by using the `handlerAnnotationSecurity` boolean setting.
* JWT Token Security Support

## Improvements

* SSL Enforcement now cascades according to the following lookup: Global, rule, request
* Interfaces documented for easier extension `interfaces.*`
* Migration to script and code modernization
* New Module Layout
* Secured rules are now logged as `warn()` with the offending Ip address.
* New setting to turn on/off the loading of the security firewall: `autoLoadFirewall`. The interceptor will auto load and be registered as `cbsecurity@global` in WireBox.

## Compat

* Adobe 11 Dropped
* Lucee 4.5 Dropped
* Migrate your root `cbSecurity` settings in your `config/ColdBox.cfc` to inside the `moduleSettings`
* IOC rules support dropped
* OCM rules support dropped
* `validatorModel` dropped in favor of just `validator` to be a WireBox Id
* Removed `preEventSecurity` it was too chatty and almost never used
* The function `userValidator` has been renamed to `ruleValidator` and also added the `annotationValidator` as well.
* `rulesSource` removed you can now use the `rules` setting
  * The `rules` can be: `array, db, model, filepath`
  * If the `filepath` has `json` or `xml` in it, we will use that as the source style
* `rulesFile` removed you can now use the `rules` setting.


# About This Book

## About This Book

The source code for this book is hosted in GitHub: <https://github.com/ortus-docs/cbsecurity-docs>. You can freely contribute to it and submit pull requests. The contents of this book is copyright by [Ortus Solutions, Corp](http://www.ortussolutions.com/) and cannot be altered or reproduced without author's consent. All content is provided *"As-Is"* and can be freely distributed.

* The majority of code examples in this book are done in `cfscript`.
* The majority of code generation and running of examples are done via **CommandBox**: The ColdFusion (CFML) CLI, Package Manager, REPL - <https://www.ortussolutions.com/products/commandbox>​

## External Trademarks & Copyrights <a href="#external-trademarks-and-copyrights" id="external-trademarks-and-copyrights"></a>

Flash, Flex, ColdFusion, and Adobe are registered trademarks and copyrights of Adobe Systems, Inc.

## Notice of Liability <a href="#notice-of-liability" id="notice-of-liability"></a>

The information in this book is distributed “as is”, without warranty. The author and Ortus Solutions, Corp shall not have any liability to any person or entity with respect to loss or damage caused or alleged to be caused directly or indirectly by the content of this training book, software and resources described in it.

## Contributing <a href="#contributing" id="contributing"></a>

We highly encourage contribution to this book and our open source software. The source code for this book can be found in our [GitHub repository](https://github.com/ortus-docs/cbsecurity-docs) where you can submit pull requests.

## Charitable Proceeds <a href="#charitable-proceeds" id="charitable-proceeds"></a>

10% of the proceeds of this book will go to charity to support orphaned kids in El Salvador - <https://www.harvesting.org/>. So please donate and purchase the printed version of this book, every book sold can help a child for almost 2 months.

### Shalom Children's Home <a href="#shalom-childrens-home" id="shalom-childrens-home"></a>

<img src="https://raw.githubusercontent.com/ortus-docs/logbox-docs/master/images/shalom.jpg" alt="" data-size="original">

**Shalom Children’s Home** is one of the ministries that is dear to our hearts located in El Salvador. During the 12 year civil war that ended in 1990, many children were left orphaned or abandoned by parents who fled El Salvador. The Benners saw the need to help these children and received 13 children in 1982. Little by little, more children came on their own, churches and the government brought children to them for care, and the Shalom Children’s Home was founded.

Shalom now cares for over 80 children in El Salvador, from newborns to 18 years old. They receive shelter, clothing, food, medical care, education and life skills training in a Christian environment. The home is supported by a child sponsorship program.

We have personally supported Shalom for over 6 years now; it is a place of blessing for many children in El Salvador that either have no families or have been abandoned. This is good earth to seed and plant.


# Author

## Luis Fernando Majano Lainez <a href="#luis-fernando-majano-lainez" id="luis-fernando-majano-lainez"></a>

![](/files/-Lp-0mh7rFCs1esEicGW)

Luis Majano is a Computer Engineer that has been developing and designing software systems since the year 2000. He was born in [San Salvador, El Salvador](http://en.wikipedia.org/wiki/El_Salvador) in the late 70’s, during a period of economical instability and civil war. He lived in El Salvador until 1995 and then moved to Miami, Florida where he completed his Bachelors of Science in Computer Engineering at [Florida International University](http://fiu.edu). Luis resides in Houston, Texas with his beautiful wife Veronica, baby girl Alexia and baby boy Lucas!

He is the CEO of [Ortus Solutions](http://www.ortussolutions.com), a consulting firm specializing in web development, ColdFusion (CFML), Java development and all open source professional services under the ColdBox and ContentBox stack. He is the creator of ColdBox, ContentBox, WireBox, MockBox, LogBox and anything “BOX”, and contributes to many open source ColdFusion/Java projects. You can read his blog at [www.luismajano.com](http://www.luismajano.com)

Luis has a passion for Jesus, tennis, golf, volleyball and anything electronic. Random Author Facts:

* He played volleyball in the Salvadorean National Team at the tender age of 17
* The Lord of the Rings and The Hobbit is something he reads every 5 years. (Geek!)
* His first ever computer was a Texas Instrument TI-86 that his parents gave him in 1986. After some time digesting his very first BASIC book, he had written his own tic-tac-toe game at the age of 9. (Extra geek!)
* He has a geek love for circuits, microcontrollers and overall embedded systems.
* He has of late (during old age) become a fan of organic gardening.

> Keep Jesus number one in your life and in your heart. I did and it changed my life from desolation, defeat and failure to an abundant life full of love, thankfulness, joy and overwhelming peace. As this world breathes failure and fear upon any life, Jesus brings power, love and a sound mind to everybody!
>
> “Trust in the LORD with all your heart, and do not lean on your own understanding.” \
> &#x20;Proverbs 3:5

## Contributors <a href="#contributors" id="contributors"></a>

### Will de Bruin <a href="#will-de-bruin" id="will-de-bruin"></a>

### Brad Wood <a href="#brad-wood" id="brad-wood"></a>


# Installation

Leverage CommandBox to install into your ColdBox app:

```bash
# Latest version
install cbsecurity

# Bleeding Edge
install cbsecurity@be
```

## System Requirements

* Lucee 5.x+
* ColdFusion 2016+

## Module Settings

The module can be configured by adding a `cbsecurity` key in the `moduleSettings` structure within the `config/Coldbox.cfc`

{% code title="config/Coldbox.cfc" %}

```javascript
// Module Settings
moduleSettings = {
    // CB Security
    cbSecurity : {
        // The global invalid authentication event or URI or URL to go if an invalid authentication occurs
        "invalidAuthenticationEvent"    : "",
        // Default Authentication Action: override or redirect when a user has not logged in
        "defaultAuthenticationAction"    : "redirect",
        // The global invalid authorization event or URI or URL to go if an invalid authorization occurs
        "invalidAuthorizationEvent"        : "",
        // Default Authorization Action: override or redirect when a user does not have enough permissions to access something
        "defaultAuthorizationAction"    : "redirect",
        // You can define your security rules here or externally via a source
        "rules"                            : [],
        // The validator is an object that will validate rules and annotations and provide feedback on either authentication or authorization issues.
        "validator"                        : "CBAuthValidator@cbsecurity",
        // The WireBox ID of the authentication service to use in cbSecurity which must adhere to the cbsecurity.interfaces.IAuthService interface.
        "authenticationService"          : "authenticationService@cbauth",
        // WireBox ID of the user service to use
        "userService"                     : "",
        // The name of the variable to use to store an authenticated user in prc scope if using a validator that supports it.
        "prcUserVariable"                 : "oCurrentUser",
        // If source is model, the wirebox Id to use for retrieving the rules
        "rulesModel"                    : "",
        // If source is model, then the name of the method to get the rules, we default to `getSecurityRules`
        "rulesModelMethod"                : "getSecurityRules",
        // If source is db then the datasource name to use
        "rulesDSN"                        : "",
        // If source is db then the table to get the rules from
        "rulesTable"                    : "",
        // If source is db then the ordering of the select
        "rulesOrderBy"                    : "",
        // If source is db then you can have your custom select SQL
        "rulesSql"                         : "",
        // Use regular expression matching on the rule match types
        "useRegex"                         : true,
        // Force SSL for all relocations
        "useSSL"                        : false,
        // Auto load the global security firewall
        "autoLoadFirewall"                : true,
        // Activate handler/action based annotation security
        "handlerAnnotationSecurity"        : true,
        // Activate security rule visualizer, defaults to false by default
        "enableSecurityVisualizer"        : false,
        // JWT Settings
 			  "jwt"                         : {
     				// The issuer authority for the tokens, placed in the `iss` claim
     				"issuer"                     : "",
     				// The jwt secret encoding key to use. This key is only effective within the `config/Coldbox.cfc`. Specifying within a module does nothing.
     				"secretKey"                  : getSystemSetting( "JWT_SECRET", "" ),
     				// by default it uses the authorization bearer header, but you can also pass a custom one as well or as an rc variable.
     				"customAuthHeader"           : "x-auth-token",
     				// The expiration in minutes for the jwt tokens
     				"expiration"                 : 60,
     				// If true, enables refresh tokens, token creation methods will return a struct instead
     				// of just the access token. e.g. { access_token: "", refresh_token : "" }
     				"enableRefreshTokens"        : false,
     				// The default expiration for refresh tokens, defaults to 30 days
     				"refreshExpiration"          : 10080,
     				// The Custom header to inspect for refresh tokens
     				"customRefreshHeader"        : "x-refresh-token",
     				// If enabled, the JWT validator will inspect the request for refresh tokens and expired access tokens
     				// It will then automatically refresh them for you and return them back as
     				// response headers in the same request according to the customRefreshHeader and customAuthHeader
     				"enableAutoRefreshValidator" : false,
     				// Enable the POST > /cbsecurity/refreshtoken API endpoint
     				"enableRefreshEndpoint"      : true,
     				// encryption algorithm to use, valid algorithms are: HS256, HS384, and HS512
     				"algorithm"                  : "HS512",
     				// Which claims neds to be present on the jwt token or `TokenInvalidException` upon verification and decoding
     				"requiredClaims"             : [],
     				// The token storage settings
     				"tokenStorage"               : {
         					// enable or not, default is true
         					"enabled"    : true,
         					// A cache key prefix to use when storing the tokens
         					"keyPrefix"  : "cbjwt_",
         					// The driver to use: db, cachebox or a WireBox ID
         					"driver"     : "cachebox",
         					// Driver specific properties
         					"properties" : { "cacheName" : "default" }
     				}
 			}
    }
};
```

{% endcode %}

{% hint style="warning" %}
If you are using cbauth as your `authenticationService` (the default), you also need to [configure cbauth.](https://cbauth.ortusbooks.com/installation-and-usage)
{% endhint %}


# Overview

In this page you will find a thorough overview of the capabilities of the ColdBox Security module.

## Authentication/Authorization

For any security system you need to know **who** is authenticated (authentication) and **what** (authorization) this user is allowed to do. `cbsecurity` is no different, so it provides an:

* **Authentication system** which performs the following functions:
  * Validates user credentials
  * Logs them in and out
  * Tracks their security in sessions or any custom storage
* **Authorization** system which:
  * validates permissions or roles or both

![](/files/-MibRo_dQtNni4Hpsjq7)

## ColdBox Security Firewall

With the ColdBox security module you will be able to **secure** all your incoming ColdBox events from execution either through security rules or discrete annotations within your code. You will also be able to leverage our `CBSecurity` service model to secure any code context anywhere.

![ColdBox Security Firewall](/files/-MibTkPJXqBEKXpSN5FW)

The module wraps itself around the `preProcess` interception point (The first execution of a ColdBox request) and will try to validate if the request has been authenticated and authorized to execute.  This is done via security rules and/or annotations on the requested handler actions through a CBSecurity `Validator` .  The job of the validator is to make sure user requests have been authenticated and authorized:

* **CBAuth Validator**: this is the default (and recommended) validator, which makes use of the [cbauth](https://cbauth.ortusbooks.com/) module. It provides authentication and *permission* based security.
* **CFML Security Validator:** Coldbox security has had this validator since version 1,  and it will talk to the ColdFusion engine's security methods (`cflogin,cflogout`). It provides authentication and *roles* based security.
* **JWT Validator**: If you want to use Json Web Tokens the JWT Validator provides authorization and authentication by validating incoming access/refresh tokens for RESTFul APIs.
* **Custom Validator:** You can define your own authentication and authorization engines and plug them in to the cbsecurity framework.

## How Does Validation Happen?

How does the interceptor know a user doesn't or does have access? Well, here is where you register a Validator CFC (`validator` setting) with the interceptor that implements two validation functions: `ruleValidator()` and `annotationValidator()` that will allow the module to know if the user is logged in and has the right authorizations to continue with the execution.

{% hint style="info" %}
You can find an interface for these methods in `cbsecurity.interfaces.ISecurityValidator`
{% endhint %}

The validator has two options to determine if the user will be allowed access:

* The `ruleValidator`() function will evaluate configured [security rules](/v2.x-3/usage/untitled-1)
* The  `annotationValidator()` function will look at [security annotations](/v2.x-3/usage/security-annotations) in your handler and handler actions.

You can use rules, annotations or even both. Rules are much more flexible, but more complex. Rules will be evaluated before annotations.

The validators' job is to tell back to the firewall if they are allowed access and if they don't, what type of validation they broke: **authentication** or **authorization**.

> `Authentication` is when a user is NOT logged in
>
> `Authorization` is when a user does not have the right permissions to access an event/handler or action.

## Validation Process

Once the firewall has the results and the user is **NOT** allowed access, the following will occur:

* The request that was blocked will be logged via LogBox with the offending IP and extra metadata
* The current requested URL will be flashed as `_securedURL` so it can be used in relocations
* If using a rule, the rule will be stored in `prc` as `cbsecurity_matchedRule`
* The validator results will be stored in `prc` as `cbsecurity_validatorResults`
* If the type of invalidation is `authentication` the `cbSecurity_onInvalidAuthentication` interception will be announced
* If the type of invalidation is `authorization` the `cbSecurity_onInvalidAuthorization` interception will be announced
* If the type is `authentication` the default action (`defaultAuthenticationAction`) for that type will be executed (An override or a relocation) will occur against the setting `invalidAuthenticationEvent` which can be an event or a destination URL.
* If the type is `authorization` the default action (`defaultAuthorizationAction`) for that type will be executed (An override or a relocation) `invalidAuthorizationEvent` which can be an event or a destination URL.

## Security Rules vs Annotation Security

{% code title="Security Rules" %}

```javascript
{
    "whitelist"     : "", 
    "securelist"    : "", 
    "match"            : "event",  // or url
    "roles"            : "", 
    "permissions"    : "", 
    "redirect"         : "", 
    "overrideEvent"    : "", 
    "useSSL"        : false, 
    "action"        : "redirect", // or override 
    "module"        : ""
};
```

{% endcode %}

{% code title="Annotations" %}

```javascript
// Secure the entire handler
component secured{

	function index(event,rc,prc){}
	function list(event,rc,prc){}

}
// Same as this
component secured=true{
}

// Do NOT secure the handler
component secured=false{
}
// Same as this, no annotation!
component{

	function index(event,rc,prc) secured{
	}

	function list(event,rc,prc) secured="list"{

	}
	 
```

{% endcode %}

Your application can be secured with security rules or handler and method annotations. Before making your choice, you should take the following arguments into consideration:

* annotations are directly visible in your code, but very static.&#x20;
* annotations can protect events. Rules can protect events and incoming Url's.
* rules allow you to change your action (override or redirect) and target on each rule. With annotations you can only use your configured default action and target.
* when stored in a file or database, rules can be edited by admins at runtime.

### Security Rules

Global Rules can be declared in your `config/ColdBox.cfc` in plain CFML or in any module's `ModuleConfig.cfc` or they can come from the following global sources:

* A json file
* An xml file
* The database by adding the configuration settings for it
* A model by executing a `getSecurityRules()` method from it

#### Rule Anatomy

A rule is a struct that can be composed of the following elements. All of them are optional except the `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) when no redirect or overrideEvent is defined in the rule.
        "module"        : "" // metadata we can add so mark rules that come from modules
    };
]
```

#### Global Rules

Rules can be declared globally in your `config/ColdBox.cfc` or they can also be place in any custom module in your application:

{% code title="config/Coldbox.cfc" %}

```javascript
// CB Security
cbSecurity : {
    // Global Relocation when an invalid access is detected, instead of each rule declaring one.
    "invalidAuthenticationEvent"     : "main.index",
    // Global override event when an invalid access is detected, instead of each rule declaring one.
    "invalidAuthorizationEvent"        : "main.index",
    // Default invalid action: override or redirect when an invalid access is detected, default is to redirect
    "defaultAuthorizationAction"    : "redirect",
    // The global security rules
    "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"
        }
    ]
    }
};
```

{% endcode %}

### Annotation Security

The firewall will inspect handlers for the `secured` annotation. This annotation can be added to the entire handler or to an action or both. The default value of the `secured` annotation is a Boolean `true`. Which means, we need a user to be authenticated in order to access it.

{% code title="handlers" %}

```javascript
// Secure this handler
component secured{

    function index(event,rc,prc){}
    function list(event,rc,prc){}

}

// Same as this
component secured=true{
}

// Not the same as this
component secured=false{
}
// Or this
component{

    function index(event,rc,prc) secured{

    }

    function list(event,rc,prc) secured="list"{

    }

}
```

{% endcode %}

#### Authorization Context

You can also give the annotation some value, which can be anything you like: A list of roles, a role, a list of permissions, metadata, etc. Whatever it is, this is the **authorization context** and the user validator must be able to not only authenticate but authorize the context or an invalid authorization will occur.

{% code title="handler/users.cfc" %}

```javascript
// Secure this handler
component secured="admin,users"{

    function index(event,rc,prc) secured="list"{

    }

    function save(event,rc,prc) secured="write"{

    }

}
```

{% endcode %}

#### Cascading Security

By having the ability to annotate the handler and also the action you create a cascading security model where they need to be able to access the handler first and only then will the action be evaluated for access as well.

## Security Validator

As we mentioned at the beginning of this overview, the security module will use a Validator object in order to determine if the user has authentication/authorization or not. This setting is the `validator` setting and will point to the WireBox ID that implements the following methods: `ruleValidator() and annotationValidator().`

{% code title="models/MyValidator.cfc" %}

```javascript
/**
 * This function is called once an incoming event matches a security rule.
 * You will receive the security rule that matched and an instance of the ColdBox controller.
 *
 * You must return a struct with two keys:
 * - allow:boolean True, user can continue access, false, invalid access actions will ensue
 * - type:string(authentication|authorization) The type of block that ocurred.  Either an authentication or an authorization issue.
 *
 * @return { allow:boolean, type:string(authentication|authorization) }
 */
struct function ruleValidator( required rule, required controller );

/**
 * This function is called once access to a handler/action is detected.
 * You will receive the secured annotation value and an instance of the ColdBox Controller
 *
 * You must return a struct with two keys:
 * - allow:boolean True, user can continue access, false, invalid access actions will ensue
 * - type:string(authentication|authorization) The type of block that ocurred.  Either an authentication or an authorization issue.
 *
 * @return { allow:boolean, type:string(authentication|authorization) }
 */
struct function annotationValidator( required securedValue, required controller );
```

{% endcode %}

Each validator must return a `struct` with the following keys:

* `allow:boolean` A Boolean indicator if authentication or authorization was violated
* `type:stringOf(authentication|authorization)` A string that indicates the type of violation: authentication or authorization.
* `messages:string` Info or debugging messages

### CBAuthValidator

ColdBox security ships with the `CBAuthValidator@cbsecurity` which is the default validator in the configuration setting `validator` setting.

```javascript
cbsecurity = {
    validator = "CBAuthValidator@cbsecurity"
}
```

{% hint style="warning" %}
When using the default `CBAuthValidator@cbsecurity` you also have to configure the cbauth module.
{% endhint %}

```javascript
  cbAuth: {
    userServiceClass: "UserService"
  }
```

### CFValidator

ColdBox security ships also with a CFML authentication and authorization validator called `CFSecurity` which has the following WireBox ID: `CFValidator@cbsecurity` and can be found at `cbsecurity.models.CFSecurity`

You basically use `cfloginuser` to log in a user and set their appropriate **roles** in the system. The module can then match to these roles via the security rules you have created.

{% embed url="<https://cfdocs.org/cfloginuser>" %}

{% embed url="<https://cfdocs.org/cflogin>" %}

{% code title="cbsecurity/models/CFValidator.cfc" %}

```javascript
struct function ruleValidator( required rule, required controller ){
    return validateSecurity( arguments.rule.roles );
}

struct function annotationValidator( required securedValue, required controller ){
    return validateSecurity( arguments.securedValue );
}

private function validateSecurity( required roles ){
    var results = { "allow" : false, "type" : "authentication" };

    // Are we logged in?
    if( isUserLoggedIn() ){

        // Do we have any roles?
        if( listLen( arguments.roles ) ){
            results.allow     = isUserInAnyRole( arguments.roles );
            results.type     = "authorization";
        } else {
            // We are satisfied!
            results.allow.true;
        }
    }

    return results;
}
```

{% endcode %}

### Custom Validators

The second method of authentication is based on your custom security logic. You will be able to register a validation object with the module. Once a rule is matched, the module will call your validation object, send in the rule/annotation value and ask if the user can access it or not. It will be up to your logic to determine if the rule is satisfied or not. Below is a sample permission based security validator:

{% code title="models/MySecurity.cfc" %}

```javascript
component singleton{

    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" };
        var user     = 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;
    }
}
```

{% endcode %}

## Authentication vs Authorization

The security module can distinguish between authentication issues and authorization issues. Once these actions are identified, the security module can act upon the result of these actions. These actions are based on the following 4 settings, but they all come down to two outcomes:

* a relocation to another event or URL
* an event override

| Setting                       | Default      | Description                                                                                                         |
| ----------------------------- | ------------ | ------------------------------------------------------------------------------------------------------------------- |
| `invalidAuthenticationEvent`  | ---          | The global invalid authentication event or URI or URL to go if an invalid authentication occurs                     |
| `defaultAuthenticationAction` | **redirect** | Default Authentication Action: override or redirect when a user has not logged in                                   |
| `invalidAuthorizationEvent`   | ---          | The global invalid authorization event or URI or URL to go if an invalid authorization occurs                       |
| `defaultAuthorizationAction`  | **redirect** | Default Authorization Action: override or redirect when a user does not have enough permissions to access something |

## Interceptions

When invalid authentication or authorizations occur the interceptor will announce the following events:

* `cbSecurity_onInvalidAuthentication`
* `cbSecurity_onInvalidAuthorization`

You will receive the following data in the `interceptData` struct:

* `ip` : The offending IP address
* `rule` : The security rule intercepted or empty if annotations
* `settings` : The firewall settings
* `validatorResults` : The validator results
* `annotationType` : The annotation type intercepted, `handler` or `action` or empty if rule driven
* `processActions` : A Boolean indicator that defaults to **true**. If you change this to **false**, then the interceptor won't fire the invalid actions. Usually this means, you manually will do them.

You can use these security listeners to do auditing, logging, or even override the result of the operation.

{% hint style="success" %}
There are many more interception points available to you, check them out in our [Interceptions](/v2.x-3/usage/interceptions) page.
{% endhint %}

## CBSecurity Model

The `CBSecurity` model was introduced in version 2.3.0 and it provides you with a way to provide authorization checks and contexts anywhere you like: handlers, layouts, views, interceptors and even models.

Getting access to the model is easy via our `cbSecure()` mixin (handlers/layouts/views/interceptors) or injecting it via WireBox:

```javascript
// Mixin approach
cbSecure()

// Injection
property name="cbSecurity" inject="@CBSecurity";
```

Once injected you can leverage it using our awesome methods listed below:

### **Blocking Methods**

When certain permission context is met, if not throws `NotAuthorized`

* `secure( permissions, [message] )`
* `secureAll( permissions, [message] )`
* `secureNone( permissions, [message] )`
* `secureWhen( context, [message] )`

```javascript
// Only allow access to user_admin
cbSecure().secure( "USER_ADMIN" );

// Only allow access if you have all of these permissions
cbSecure().secureAll( "EDITOR, POST_PUBLISH" )

// YOu must not have this permission, if you do, kick you out
cbSecure().secureNone( "FORGEBOX_USER" )

// Secure using security evaluations
// Kick out if you do not have the AUTHOR_ADMIN or you are not the same incoming author
cbSecurity.secureWhen( 
    cbSecurity.none( "AUTHOR_ADMIN" ) && 
    !cbSecurity.sameUser( oAuthor )  
)

// Secure using a closure 
cbSecurity.secureWhen( ( user ) => !user.isConfirmed() );
```

### **Action Context Methods**

When certain permission context is met, execute the success function/closure, else if a `fail` closure is defined, execute that instead.

* `when( permissions, success, fail )`
* `whenAll( permissions, success, fail )`
* `whenNone( permissions, success, fail )`

```javascript
var oAuthor = authorService.getOrFail( rc.authorId );
prc.data = userService.getData();

// Run Security Contexts
cbSecure()
    // Only user admin can change to the incoming role
    .when( "USER_ADMIN", ( user ) => oAuthor.setRole( roleService.get( rc.roleID ) ) )
    // The system admin can set a super admin
    .when( "SYSTEM_ADMIN", ( user ) => oAuthor.setRole( roleService.getSystemAdmin() ) )
    // Filter the data to be shown to the user
    .when( "USER_READ_ONLY", ( user ) => prc.data.filter( ( i ) => !i.isClassified ) )

// Calling with a fail closure
cbSecurity.when(
    "USER_ADMIN",
    ( user ) => user.setRole( "admin" ), //success
    ( user ) => relocate( "Invaliduser" ) //fail
);
```

### **Verification Methods**

Verify permissions or user equality

* `has( permissions ):boolean`
* `all( permissions ):boolean`
* `none( permissions ):boolean`
* `sameUser( user ):boolean`

```javascript
function edit( event, rc, prc ){
    var oUser = userService.getOrFail( rc.id ?: "" );
    if( !sameUser( oUser ) ){
        relocate( "/users" );
    }
}

<cfif cbsecure().all( "USER_ADMIN,USER_EDITOR" )>
    This is only visible to user admins!
</cfif>

<cfif cbsecure().has( "SYSTEM_ADMIN" )>
    <a href="/user/impersonate/#prc.user.getId()#">Impersonate User</a>
</cfif>

<cfif cbsecure().sameUser( prc.user )>
    <i class="fa fa-star">This is You!</i>
</cfif>
```

### **Request Context Methods**

* `secureView( permissions, successView, failView )`

{% code title="handlers/users.cfc" %}

```javascript
component{

    function index( event, rc, prc ){
     event.secureView( "USER_ADMIN", "users/admin/index", "users/index" ); 
    }

}
```

{% endcode %}

## Security Visualizer

This module also ships with a security visualizer that will document all your security rules and your settings in a nice panel. In order to activate it you must add the `enableSecurityVisualizer` setting to your config and mark it as `true`. Once enabled you can navigate to: `/cbsecurity` and you will be presented with the visualizer.

{% hint style="danger" %}
**Important** The visualizer is disabled by default and if it detects an environment of production, it will disable itself.
{% endhint %}

![](https://raw.githubusercontent.com/coldbox-modules/cbsecurity/development/test-harness/visualizer.png)

## JSON Web Tokens (JWT) REST Security

ColdBox Security offers a comprehensive feature set for RESTFul applications that require JSON web tokens.  We offer both access and refresh token capabilities.  Check out our [JWT Section](/v2.x-3/jwt/jwt-services) for an in-depth overview.


# Configuration

## Security Settings

By Default, the security module will register itself for you using the module configuration settings you define in the`config/ColdBox.cfc.` Below you can find all the settings with their default value and description.

{% code title="config/Coldbox.cfc" %}

```javascript
// Module Settings
moduleSettings = {
    // CB Security
    cbSecurity : {
        // The global invalid authentication event or URI or URL to go if an invalid authentication occurs
        "invalidAuthenticationEvent"    : "",
        // Default Authentication Action: override or redirect when a user has not logged in
        "defaultAuthenticationAction"    : "redirect",
        // The global invalid authorization event or URI or URL to go if an invalid authorization occurs
        "invalidAuthorizationEvent"        : "",
        // Default Authorization Action: override or redirect when a user does not have enough permissions to access something
        "defaultAuthorizationAction"    : "redirect",
        // You can define your security rules here or externally via a source
        // specify an array for inline, or a string (db|json|xml|model) for externally
        "rules"                            : [],
        // The validator is an object that will validate rules and annotations and provide feedback on either authentication or authorization issues.
        "validator"                        : "CBAuthValidator@cbsecurity",
        // The WireBox ID of the authentication service to use in cbSecurity which must adhere to the cbsecurity.interfaces.IAuthService interface.
        "authenticationService"          : "authenticationService@cbauth",
        // WireBox ID of the user service to use
        "userService"                     : "",
        // The name of the variable to use to store an authenticated user in prc scope if using a validator that supports it.
        "prcUserVariable"                 : "oCurrentUser",
        // If source is model, the wirebox Id to use for retrieving the rules
        "rulesModel"                    : "",
        // If source is model, then the name of the method to get the rules, we default to `getSecurityRules`
        "rulesModelMethod"                : "getSecurityRules",
        // If source is db then the datasource name to use
        "rulesDSN"                        : "",
        // If source is db then the table to get the rules from
        "rulesTable"                    : "",
        // If source is db then the ordering of the select
        "rulesOrderBy"                    : "",
        // If source is db then you can have your custom select SQL
        "rulesSql"                         : "",
        // Use regular expression matching on the rule match types
        "useRegex"                         : true,
        // Force SSL for all relocations
        "useSSL"                        : false,
        // Auto load the global security firewall
        "autoLoadFirewall"                : true,
        // Activate handler/action based annotation security
        "handlerAnnotationSecurity"        : true,
        // Activate security rule visualizer, defaults to false by default
        "enableSecurityVisualizer"        : false,
        // JWT Settings
        "jwt"                             : {
            // The issuer authority for the tokens, placed in the `iss` claim
            "issuer"                  : "",
            // The jwt secret encoding key to use
            "secretKey"               : getSystemSetting( "JWT_SECRET", "" ),
            // by default it uses the authorization bearer header, but you can also pass a custom one as well or as an rc variable.
            "customAuthHeader"        : "x-auth-token",
            // The expiration in minutes for the jwt tokens
            "expiration"              : 60,
            // If true, enables refresh tokens, longer lived tokens (not implemented yet)
            "enableRefreshTokens"     : false,
            // The default expiration for refresh tokens, defaults to 30 days
            "refreshExpiration"       : 43200,
            // encryption algorithm to use, valid algorithms are: HS256, HS384, and HS512
            "algorithm"               : "HS512",
            // Which claims neds to be present on the jwt token or `TokenInvalidException` upon verification and decoding
            "requiredClaims"          : [] ,
            // The token storage settings
            "tokenStorage"            : {
                // enable or not, default is true
                "enabled"       : true,
                // A cache key prefix to use when storing the tokens
                "keyPrefix"     : "cbjwt_",
                // The driver to use: db, cachebox or a WireBox ID
                "driver"        : "cachebox",
                // Driver specific properties
                "properties"    : {
                    "cacheName" : "default"
                }
            }
        }
    }
};
```

{% endcode %}

## InvalidAuthentication-/ InvalidAuthorization events and default actions

The `invalidAuthenticationEvent` and `invalidAuthorizationEvent` keys can be used to provide default events when Authentication or Authorization failed. The defaultAuthenticationAction and defaultAuthorizationAction determine whether there will be a redirection or override. The default action is `redirect`, but especially for API's an `override` will be more appropriate. When using rule-based security you can override these keys for any individual rule.

## Validator

You can place a global validator in the configuration settings, but you can also override the validator on a module by module basis as well. The default validator is using the [CBAuth Validator.](/v2.x-3/security-validators/cbauth-validator)

## Authentication Services

cbsecurity ships with the [cbauth](https://github.com/elpete/cbauth) module that can provide you with a nice interface for authentication services. If you use the default `authenticationService` authenticationService\@cbauth, you have to define the UserServiceClass in the cbauth module.\
However, you can plug in any WireBox ID and select your own authentication services.

{% hint style="warning" %}
If you are using cbauth as your `authenticationService` (the default), you also need to [configure cbauth.](https://cbauth.ortusbooks.com/installation-and-usage)
{% endhint %}

## User Services

cbsecurity will also require a user service if you will be dealing with any JWT security tokens. Just add your WireBox ID to the user service of your choice. If you are using cbauth, you have to define the UserServiceClass in the cbauth module.

## Automatic Firewall

Please note that by default, the security firewall will be auto-registered for you. If you do NOT want the firewall to be automatically registered for you, then use the `autoLoadFirewall` setting and make it false. Then you can use the **Custom Firewall** approach below to register the firewall manually in the order of the interceptors that you would like.

```javascript
autoLoadFirewall : false
```

## Annotation Security

By default, annotation security is enabled. This will inspect ALL incoming event executions for the security annotations. If you do not want to use annotation security we recommend you turn it off to avoid the inspection of events.

```javascript
handlerAnnotationSecurity : false
```

## Security Visualizer

ColdBox security comes with a nice graphical visualizer for all the registered security rules and settings in your global firewall. You can enable it by using the enableSecurityVisualizer setting.

```javascript
enableSecurityVisualizer :  true
```

You can then visit the `/cbsecurity` URL and you will be presented with this magical tool:

![](https://raw.githubusercontent.com/coldbox-modules/cbsecurity/development/test-harness/visualizer.png)

{% hint style="danger" %}
**Important** The visualizer is **disabled** by default and if it detects an environment of production, it will disable itself.
{% endhint %}

## Module Settings

Each module can override some settings for cbsecurity according to its needs. You will create a `cbsecurity` struct within the module's `settings` struct in the `ModuleConfig.cfc`

{% code title="module/ModuleConfig.cfc" %}

```javascript
settings = {
    // CB Security Module Settings
    cbsecurity : {
        // Module Relocation when an invalid access is detected, instead of each rule declaring one.
        "invalidAuthenticationEvent"  : "api:Home.onInvalidAuth",
        // Default Auhtentication Action: override or redirect 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"   : "api:Home.onInvalidAuthorization",
        // Default invalid action: override or redirect when an invalid access is detected, default is to redirect
        "defaultAuthorizationAction"  : "override",
        // The validator to use for this module
        "validator"                   : "JWTService@cbsecurity",
        // You can define your security rules here or externally via a source
        "rules"                       : [ { "secureList" : "api:Secure\.*" } ]
    }
}
```

{% endcode %}

The settings you see above are the only ones that module's support as of now.

## Custom Firewalls

You can also register multiple instances of the `cbsecurity` module using different configurations by just adding them to your app's config or even your module's configuration. This will register a NEW firewall apart from the global security firewall registered using the global settings as defined above.

{% code title="config/Coldbox.cfc" %}

```javascript
interceptors = [

    {
        class="cbsecurity.interceptors.Security",
        name="FirewallName",
        properties={
            // All Settings from above
        }

]
```

{% endcode %}


# Rule Sources

The security firewall can be configured with rules that can come from many different sources:

* Declared inline in your `config/Coldbox.cfc`
* A JSON file
* An XML file
* From a model object via a method call
* From a database
* Declared inline in ANY module's `ModuleConfig.cfc`

{% hint style="warning" %}
When defining your rules source, you **ALWAYS** have to define the `rules` property. You specify an array of rules for inline, or \
`rules = "(db|json|xml|model)"`\
if you define your rules externally.\
If you have external rules you probably have to specify additional properties as explained in the next pages.
{% endhint %}

Let's start exploring these sources.


# DB Rules

If you have your security rules in a database, then cbsecurity can read the rules from the database for you.  Just **make** **the `rules` key  equal to `db`** and fill out the extra configuration keys shown below:

| Property       | Type   | Required | Default                   | Description                                                                                                                                                   |
| -------------- | ------ | -------- | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `rulesDSN`     | string | true     | ---                       | The dsn to use if the rules are coming from a database                                                                                                        |
| `rulesTable`   | string | true     | ---                       | The table where the rules are                                                                                                                                 |
| `rulesSQL`     | string | false    | `select* from rulesTable` | The custom SQL statement to use to retrieve the rules according to the rulesTable property. If not set, the default of select\* from rulesTable will be used. |
| `rulesOrderBy` | string | false    | ---                       | The column to order the rules by. If not chosen, the interceptor will not order the query, just select it.                                                    |

{% code title="config/Coldbox.cfc" %}

```javascript
moduleSettings = {
	// CB Security
	cbSecurity : {
		rules        : "db", // Rules are in the database
		rulesDSN     : "myDatasource", // The datasource
		rulesTable   : "securityRules", // The table that has the rules
		rulesOrderBy : "order asc" // An optional ordering
	}
};
```

{% endcode %}


# Inline Rules

Inline rules will be used by declaring them in your configuration for **cbsecurity** in the `config/ColdBox.cfc.`  This is done by making the `rules` key an array of rule structures.

{% code title="config/Coldbox.cfc" %}

```javascript
moduleSettings = {
	// CB Security
	cbSecurity : {
		// The global security rules
		"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"
			}
		]
	}
};
```

{% endcode %}


# JSON Rules

If you have already a JSON file with your rules, then all you need to do is add the path (relative or absolute) to that file in the `rules` configuration key.  However, the path MUST include the keyword `json` in it.

{% code title="config/Coldbox.cfc" %}

```javascript
moduleSettings = {
	// CB Security
	cbSecurity : {
		"rules" : "config/security.json.cfm"
};
```

{% endcode %}

\
Then your file can be something like this:

{% code title="config/security.json.cfm" %}

```javascript
[
    {
        "whitelist": "user\\.login,user\\.logout,^main.*",
        "securelist": "^user\\.*, ^admin",
        "match": "event",
        "roles": "admin",
        "permissions": "",
        "redirect": "user.login",
        "useSSL": false
    },
    {
        "whitelist": "",
        "securelist": "^shopping",
        "match": "url",
        "roles": "",
        "permissions": "shop,checkout",
        "redirect": "user.login",
        "useSSL": true
    }
]
```

{% endcode %}


# Model Rules

If you prefer to store your rules your way, then that's perfectly fine.  Just **make your `rules` setting point to `model`** and then provide us with the object to get the rules from.

| Property           | Type   | Required | Default            | Description                                                              |
| ------------------ | ------ | -------- | ------------------ | ------------------------------------------------------------------------ |
| `rulesModel`       | string | true     | ---                | The WireBox ID of the object that we will use to retrieve the rules from |
| `rulesModelMethod` | string | false    | `getSecurityRules` | The name of the method to call on the object.                            |

{% code title="config/Coldbox.cfc" %}

```javascript
moduleSettings = {
	// CB Security
	cbSecurity : {
		"rules" 		: "model",
		"rulesModel" 	: "SecurityService"
	}
};
```

{% endcode %}

<br>


# Module Rules

Every module in ColdBox has the capability to contribute their own rules to `cbsecurity` by registering them in the `ModuleConfig.cfc` within the `settings` struct. Just create another struct called `cbsecurity` with the following allowed keys:

{% code title="ModuleConfig.cfc" %}

```javascript
settings = {
    // CB Security Rules to prepend to global rules
    cbsecurity = {
        // Module Relocation when an invalid access is detected, instead of each rule declaring one.
        "invalidAuthenticationEvent"     : "mod1:secure.index",
        // Default Authentication Action: override or redirect when a user has not logged in
        "defaultAuthenticationAction"    : "redirect",
        // 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 when a user does not have enough permissions to access something
        "defaultAuthorizationAction"    : "redirect",
        // You can define your security rules here
        "rules"                            : [
            {
                "secureList"     : "mod1:home"
            },
            {
                "secureList"     : "mod1/modOverride",
                "match"            : "url",
                "action"        : "override"
            }
        ]
    }
};
```

{% endcode %}

As you can see each module can have it's own overrides for authentication and authorization events as well as their own rules.

{% hint style="danger" %}
Please note that these security rules will be **PREPENDED** to the global rules
{% endhint %}

## Rule Sources

As with the global rules defined in `config/Coldbox.cfc`, the module `cbsecurity.rules` setting supports multiple rule sources:

* [DB](https://github.com/ortus-docs/cbsecurity-docs/tree/ea50160182c145dae1aa01e169fc434048a3c911/getting-started/first-chapter/rule-sources/untitled/README.md)
* [Inline](https://github.com/ortus-docs/cbsecurity-docs/tree/ea50160182c145dae1aa01e169fc434048a3c911/getting-started/first-chapter/rule-sources/inline-rules/README.md)
* [JSON](https://github.com/ortus-docs/cbsecurity-docs/tree/ea50160182c145dae1aa01e169fc434048a3c911/getting-started/first-chapter/rule-sources/json-properties/README.md)
* [Model](https://github.com/ortus-docs/cbsecurity-docs/tree/ea50160182c145dae1aa01e169fc434048a3c911/getting-started/first-chapter/rule-sources/model-rules/README.md)
* [XML](https://github.com/ortus-docs/cbsecurity-docs/tree/ea50160182c145dae1aa01e169fc434048a3c911/getting-started/first-chapter/rule-sources/xml-properties/README.md)

For example, you can load security rules specific to a module from a JSON file stored in your module:

{% code title="ModuleConfig.cfc" %}

```
```

{% endcode %}

```javascript
settings = {
    cbsecurity = {
        "rules" : "#modulePath#/config/firewallRules.json"
        // other config here... <---
    }
};
```

## Loading/Unloading

Also note that if modules are loaded dynamically, it will still inspect them and register them if cbsecurity settings are found. The same goes for unloading, the entire security rules for that module will cease to exist.


# XML Rules

If you have already an XML file with your rules, then all you need to do is add the path (relative or absolute) to that file in the `rules` configuration key.  However, the path MUST include the keyword `XML` in it.

{% code title="config/Coldbox.cfc" %}

```javascript
moduleSettings = {
	// CB Security
	cbSecurity : {
		"rules" : "config/security.xml.cfm"
};
```

{% endcode %}

Then your xml file can look like this:

{% code title="config/security.xml.cfm" %}

```markup
<?xml version="1.0" encoding="ISO-8859-1"?>
<-- <
Declare as many rule elements as you want, order is important 
Remember that the securelist can contain a list of regular
expressions if you want

ex: All events in the user handler
 user\..*
ex: All events
 .*
ex: All events that start with admin
 ^admin

If you are not using regular expressions, just write the text
that can be found in an event.
-->
<rules>
    <rule>
        <match>event</match>
        <whitelist>user\.login,user\.logout,^main.*</whitelist>
        <securelist>^user\..*, ^admin</securelist>
        <roles>admin</roles>
        <permissions>read,write</permissions>
        <redirect>user.login</redirect>
    </rule>

    <rule>
           <match>event</match>
        <whitelist></whitelist>
        <securelist>^moderator</securelist>
        <roles>admin,moderator</roles>
        <permissions>read</permissions>
        <redirect>user.login</redirect>
    </rule>

    <rule>
           <match>url</match>
        <whitelist></whitelist>
        <securelist>/secured.*</securelist>
        <roles>admin,paid_subscriber</roles>
        <permissions></permissions>
        <redirect>user.pay</redirect>
    </rule>
</rules>
```

{% endcode %}


# Authentication Services

ColdBox security can work with ANY authentication service provider.

You can register ANY authentication provider with **cbsecurity** by using the `authenticationService` setting. The value must be a valid WireBox Id and the object must adhere to the following [interface](/v2.x-3/usage/authentication-services#authentication-service-interface). The authentication services can be used in conjunction with our JWT services and more features coming in the future.

```javascript
// CB Security
cbSecurity : {
    
    // The WireBox ID of the authentication service to use in cbSecurity which must adhere to the cbsecurity.interfaces.IAuthService interface.
    "authenticationService" : "authenticationService@cbauth"
    
}
```

{% hint style="info" %}
Please note that **cbauth** already implements this interface and is included with **cbsecurity** as a dependency.
{% endhint %}

{% hint style="warning" %}
If you are using cbauth as your `authenticationService` (the default), you also need to [configure cbauth.](https://cbauth.ortusbooks.com/installation-and-usage)
{% endhint %}

## Authentication Service Interface

This interface has been provided by convenience and it is not mandatory at runtime (`cbsecurity.interfaces.IAuthService`)

{% code title="cbsecurity.interfaces.IAuthService.cfc" %}

```javascript
/**
 * Copyright since 2016 by Ortus Solutions, Corp
 * www.ortussolutions.com
 * ---
 * If you register an authentication service with cbsecurity it must adhere to this interface
 */
interface{

    /**
     * Get the authenticated user
     *
	   * @throws NoUserLoggedIn : If the user is not logged in
	   *
     * @return User that implements IAuthUser
     */
    any function getUser();

    /**
     * Verifies if a user is logged in
     */
    boolean function isLoggedIn();

    /**
     * Try to authenticate a user into the system. If the authentication fails an exception is thrown, else the logged in user object is returned
     *
     * @username The username to log in with
     * @password The password to log in with
     *
     * @throws InvalidCredentials
	   *
	   * @return User : The logged in user object
     */
    any function authenticate( required username, required password );

    /**
  	 * Login a user into our persistent scopes
  	 *
  	 * @user The user object to log in
  	 *
  	 * @return The same user object so you can do functional goodness
	   */
    function login( required user );

    /**
     * Logs out the currently logged in user from the system
     */
    function logout();


}
```

{% endcode %}

You can find the information for **cbauth** in its own book:

{% embed url="<https://cbauth.ortusbooks.com>" %}

{% hint style="warning" %}
If you are using cbauth as your `authenticationService` (the default), you also need to [configure cbauth.](https://cbauth.ortusbooks.com/installation-and-usage)
{% endhint %}

## User Interface

As you can see from above, the authentication services all expect a `User` object to model your user in the system. So your `User` object must also adhere to the following methods modeled by the `cbsecurity.interfaces.IAuthUser` interface. This will allow the validators and JWT services to get the appropriate data it needs.

{% code title="cbsecurity.interfaces.IAuthUser.cfc" %}

```javascript
interface{

    /**
     * Return the unique identifier for the user
     */
    function getId();

    /**
     * Verify if the user has one or more of the passed in permissions
     *
     * @permission One or a list of permissions to check for access
     *
     */
    boolean function hasPermission( required permission );

}
```

{% endcode %}

## User Services

If you will be using **cbauth** or any of our JWT features, then we will also require you register a user service class that can provide us with the right data to encapsulate security using the `userService` setting. We have provided this interface for your usage:

{% code title="cbsecurity.interfaces.IUserService.cfc" %}

```javascript
interface{

    /**
     * Verify if the incoming username/password are valid credentials.
     *
     * @username The username
     * @password The password
     */
    boolean function isValidCredentials( required username, required password );

    /**
     * Retrieve a user by username
     *
     * @return User that implements JWTSubject and/or IAuthUser
     */
    function retrieveUserByUsername( required username );

    /**
     * Retrieve a user by unique identifier
     *
     * @id The unique identifier
     *
     * @return User that implements JWTSubject and/or IAuthUser
     */
    function retrieveUserById( required id );
}
```

{% endcode %}

{% hint style="warning" %}
If using `cbauth`, you also have to specify the `UserServiceClass` key in the **cbauth** module settings.
{% endhint %}

{% hint style="info" %}
Remember that the User Service setting is only required if you will be using JWT token security
{% endhint %}


# Security Rules

We have seen how the module works on the concept of rules and how to declare them. Before we dig deeper and decompose the rules let's have a look at the processing of the rules first.

## Rule Anatomy

Each rule is modeled by a struct with keys in it:

```javascript
{
    "whitelist"     : "", 
    "securelist"    : "", 
    "match"            : "event",  // or url
    "roles"            : "", 
    "permissions"    : "", 
    "redirect"         : "", 
    "overrideEvent"    : "", 
    "useSSL"        : false, 
    "action"        : "redirect", // or override 
    "module"        : ""
};
```

The only required key is the `secureList` which is what you are trying to secure. The rest are optional and described below. Please note that you can add as many keys as you like to your security rules, which can contain much more context and information for the validators to use for validation.

{% hint style="warning" %}
Please remember that by default the secure and white lists are evaluated as regular expressions. You can turn that off in your [configuration settings.](/v2.x-3/getting-started/first-chapter)
{% endhint %}

## Rules processing

When processing rules, it is important to realize these rules come as an array which will be processed in **order**, so make sure your more specific rules will be processed **before** the more generic ones.

![cbsecurity rules processing](/files/-M8karM9MbAuAc7TQtbK)

## Rule Elements

| Property        | Type         | Description                                                                                                                                             |
| --------------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `match`         | event or URL | Determines if it needs to match the incoming URL or the incoming event. By default it matches the incoming event.                                       |
| `whitelist`     | varchar      | A comma delimited list of events or regex patterns to whitelist or to bypass security on if a match is made on the `secureList`                         |
| `securelist`    | varchar      | A comma delimited list of events or regex patterns to secure                                                                                            |
| `roles`         | varchar      | A comma delimited list of roles that can access these secure events                                                                                     |
| `permissions`   | varchar      | A comma delimited list of permissions that can access these secure events                                                                               |
| `redirect`      | varchar      | An event or route to redirect if the user is not authenticated or authorized                                                                            |
| `overrideEvent` | varchar      | The event to override using ColdBox's `event.overrideEvent()` if the user if not authenticated or authorized                                            |
| `useSSL`        | Boolean      | If true, force SSL, else use whatever the request protocol is                                                                                           |
| `action`        | string       | The action to use (redirect or override) when no explicit overrideEvent or redirect elements are defined.  If not set, then we use the global settings. |

## Rule Overrides

As we saw from the overview and our configuration sections. We can declare the default actions for authorizations and authentication issues and to which events/URLs to go if that happens. There can be a time where you can override those global/module settings directly within a rule. Let's explore those overrides:

### Redirect

If you add a `redirect` element, then you will be explicitly overriding the global/module setting and if a match is made a redirect will occur.

```javascript
{
    "secureList" : "*",
    "redirect" : "mysecret.event"
}
```

### OverrideEvent

If you add an `overrideEvent` element, then you will be explicitly overriding the global/module setting and an event override will occur.

```javascript
{
    "secureList" : "*",
    "overrideEvent" : "main.onInvalidEvent"
}
```

### Action

If you add a `action` element, then you will be explicitly overriding the global/module setting and the action will be based on this value (`override` or `event`)

```javascript
{
    "secureList" : "^api.*",
    "action" : "override"
}
```

## White Lists

If a rule has a white list, then it means that you can declare what are the exceptions to ALLOW if the incoming URL/event was matched against the `securedList`. This is a great way to say, hey secure all but allow the following events:

```javascript
{
    "secureList" : ".*",
    "whitelist : "^login"
}
```

{% hint style="danger" %}
Please note: if a rule has a whiteList, it only applies to the **current** rule. So if the whitelist matches, it the current rule is skipped and the process continues to the next rule.
{% endhint %}

Sometimes you want to make sure ALL events are secured, except for the ones specified, such as login events. If you add new functionality to your app it is easy to forget a new rule. To prevent unwanted access you could specify a LAST rule, which matches ALL event but NO permission at all. In that case you have to add a whitelist for all events which should still pass, for example:

```javascript
{
    "secureList" : ".*",
    "whitelist" : "login",
    "permissions" : "nonExistingPermission"
}
```


# Security Annotations

The security module also allows you to secure your events via annotations instead of using security rules.  The setting that controls this security feature is the `handlerAnnotationSecurity` which can see in the [configuration section.](/v2.x-3/getting-started/first-chapter#annotation-security)

The security module has a tiered approach to annotation security as it will check the handler component first and then the requested action method second.  You can apply different security contexts to each level as you see fit.

{% hint style="warning" %}
Please note that the security rules will be inspected first, annotations second.
{% endhint %}

See the diagram below for inspecting security based on annotations:

![Annotation based security](/files/-M8lAzQ_KnAxZ_FFxGRS)

## `Secure` Annotation

The firewall will inspect handlers for a `secured` annotation. This annotation can be added to the entire handler or to an action method or both. The default value of the `secured` annotation is a Boolean `true`. Which means, we need a user to be **authenticated** in order to access it.

```javascript
// Secure the entire handler
component secured{

	function index(event,rc,prc){}
	function list(event,rc,prc){}

}
// Same as this
component secured=true{
}

// Do NOT secure the handler
component secured=false{
}
// Same as this, no annotation!
component{

	function index(event,rc,prc) secured{
	}

	function list(event,rc,prc) secured="list"{

	}
	
}
```

## Authorization Context

You can also give the annotation a value, which can be anything you like: A list of roles, a role, a list of permissions, metadata, JSON, etc. Whatever it is, this is called the **authorization context** and the user validator must be able to not only authenticate but **authorize** the context or an invalid **authorization** will occur.

```javascript
// Secure this handler
component secured="admin,users"{

	function index(event,rc,prc) secured="list"{

	}
	
	function save(event,rc,prc) secured="write"{

	}

}
```

The secured value will be passed to the validator's for authorization.

## Cascading Security

By having the ability to annotate the handler and also the action you create a cascading security model where they need to be able to access the handler first **and only then** will the action be evaluated for access as well.


# Secured URL

## `_securedURL`

The security module has the concept of a secured URL which is the actual URL that got intercepted and relocated because of a security exception. If the module detects an invalid authentication or authorization and an action must be issued, then the firewall will store this URL in the `RC` scope and flash it so it can be available in the next request (if a relocation occurs).

The flash RAM variable is called: `_securedURL`. This key will be persisted in the flash memory of the framework and when the user gets relocated to the `redirect` element, this key will be populated in the request collection automatically for you.

So always remember to use this key if you want to provide a seamless login experience to your users. You can easily place it in the login form:

```markup
#html.startForm(action=prc.xehDoLogin,name="loginForm")#

    #html.hiddenField(name="_securedURL",value=event.getValue('_securedURL',''))#

    #html.textfield(name="username",label="Username: ",size="40",required="required",class="textfield",value=prc.rememberMe)#
    #html.passwordField(name="password",label="Password: ",size="40",required="required",class="textfield")#

    <div id="loginButtonbar">
        #html.checkBox(name="rememberMe",value=true,checked=(len(prc.rememberMe)))# 
        #html.label(field="rememberMe",content="Remember Me  ",class="inline")#
        #html.submitButton(value="  Log In  ",class="buttonred")#
    </div>

    <br/>
    <img src="#prc.cbRoot#/includes/images/lock.png" alt="lostPassword" />
    <a href="#event.buildLink(prc.xehLostPassword)#">Lost your password?</a> 

#html.endForm()#
```


# Interceptions

The security firewall will announce some interception events when invalid access or authorizations occur within the system:

* `cbSecurity_onInvalidAuthentication`
* `cbSecurity_onInvalidAuthorization`

You will receive the following data in the `interceptData` struct in each interception call:

* `ip` : The offending IP address
* `rule` : The security rule intercepted or empty if annotations
* `settings` : The firewall settings
* `validatorResults` : The validator results
* `annotationType` : The annotation type intercepted, `handler` or `action` or empty if rule driven
* `processActions` : A Boolean indicator that defaults to true. If you change this to false, then the interceptor won't fire the invalid actions. Usually this means, you manually will do them.

With these interceptions you can build a nice auditing system, login tracking and much more.

{% code title="interceptors/SecurityAudit.cfc" %}

```javascript
component extends="coldbox.system.Interceptor"{

    function cbSecurity_onInvalidAuthentication( event, interceptData ){
        // do what you like here
    }
    
    function cbSecurity_onInvalidAuthorization( event, interceptData ){
        // do what you like here
    }

}
```

{% endcode %}

## Stop Processing Actions

The intercept data has a key called `processActions` which defaults to **true**.  This Boolean indicator tells the firewall to process the invalid authentication/authorization procedures.  If you change this value to **false**, then the firewall will do NOTHING because it is expecting for YOU to have done the actions.

## JWT Interception

If you are using our [JWT facilities](/v2.x-3/jwt/jwt-services), then we will announce the following interceptions during JWT usage:

* `cbSecurity_onJWTCreation`
* `cbSecurity_onJWTInvalidation`
* `cbSecurity_onJWTValidAuthentication`
* `cbSecurity_onJWTInvalidUser`
* `cbSecurity_onJWTInvalidClaims`
* `cbSecurity_onJWTExpiration`
* `cbSecurity_onJWTStorageRejection`
* `cbSecurity_onJWTValidParsing`
* `cbSecurity_onJWTInvalidateAllTokens`

Check them all out in our [JWT Interceptions Page](/v2.x-3/jwt/jwt-interceptions).

## CBAuth Interceptions

You can always find the latest interception points here:

{% embed url="<https://cbauth.ortusbooks.com/interception-points>" %}

cbauth announces several custom interception points. You can use these interception points to change request data or add additional values to session or request scopes. The `preAuthentication` and `postAuthentication` events fire during the standard `authenticate()` method call with a username and password. The `preLogin` and `postLogin` events fire during the `login()` method call. The `preLogout` and `postLogout` events fire during the `logout()` method call.

{% hint style="success" %}
The `preLogin` and `postLogin` interception points will be called during the course of `authenticate()`. The order of the calls then are `preAuthentication` -> `preLogin` -> `postLogin` -> `postAuthentication`.
{% endhint %}


# cbSecurity Model

This object is used to provide you with human, fluent and explicit security authorizations and contexts.

## Explicit Authorizations

The `cbSecurity` model is a specialized service that will allow you to do explicit authorizations in any layer of your ColdBox application.

There will be times where you will need authorization checks outside of the incoming request rules or the handler annotations. This can be from within interceptors, models, layouts or even views. For this, we have provided the `cbSecurity` model so you can do explicit authorization checks anywhere you like.

## `cbSecurity` Model

You can inject our model or you can use our handy `cbsecure()` mixin (handlers/layouts/views) and then call the appropriate security functions:

```javascript
// Mixin: Handlers/Layouts/Views
cbsecure()

// Injection
property name="cbSecurity" inject="@cbSecurity"
```

{% hint style="danger" %}
All security methods will call the application's configured Authentication Service to retrieve the currently logged in user. If the user is not logged in an immediate `NoUserLoggedIn` exception will be thrown by all methods.
{% endhint %}

You can now discover our sections for securing using `cbSecurity`

* [Secure() blocking methods](/v2.x-3/usage/cbsecurity-model/secure-blocking-methods)
* [Verification Methods](/v2.x-3/usage/cbsecurity-model/verification-methods)
* [Authorization Contexts](/v2.x-3/usage/cbsecurity-model/authorization-contexts)
* [Securing Views](/v2.x-3/usage/cbsecurity-model/securing-views)

## `cbSecurity` Method Summary

### **Blocking Methods**

When certain permission context is met, if not throws `NotAuthorized`

* `secure( permissions, [message] )`
* `secureAll( permissions, [message] )`
* `secureNone( permissions, [message] )`
* `secureWhen( context, [message] )`
* `guard() alias to secure()`

### **Action Context Methods**

When certain permission context is met, execute the success function/closure, else if a `fail` closure is defined, execute that instead.

* `when( permissions, success, fail )`
* `whenAll( permissions, success, fail )`
* `whenNone( permissions, success, fail )`

### **Verification Methods**

Verify permissions or user equality

* `has( permissions ):boolean`
* `all( permissions ):boolean`
* `none( permissions ):boolean`
* `sameUser( user ):boolean`

### **Request Context Methods**

* `secureView( permissions, successView, failView )`


# secure() Blocking Methods

### The `secure()` Methods

Now that you have access to the model, you can use the following method to verify explicit permissions and authorize access. This method will **throw an exception** if the user does not validate the incoming permissions context (`NotAuthorized`).

```javascript
// Verify the currently logged in user has at least one of those permissions, 
// else throw a NotAuthorized exception
cbSecurity.secure( permissions, [message] );
cbsecure().secure( permissions, [message] );
```

* The `permission` can be an array, string or list of the permissions to validate. The user must have at least one of the permissions specified.
* The `message` is a custom error message to be used in the `message` string of the exception thrown.

You also have two more authorization methods that will verify certain permission conditions for you:

```javascript
// Authorize that the user has ALL of the incoming permissions
cbSecurity.secureAll( permissions, [message] );
// Authorize that the user has NONE of the incoming permissions
cbSecurity.secureNone( permissions, [message] );
```

### Conditional Authorizations Using `when()`

There are also cases where you want to execute a piece of code by determining if the user has access to do so. For example, only a `USER_ADMIN` can change people's roles or you want to filter some data for certain users. For this, we have created the `when()` method with the following signature:

```javascript
when( permissions, success, fail )
```

* The `permissions` is a permission array or list that will be Or'ed&#x20;
* The `success` is a closure/lambda or UDF that will execute if the permissions validate. &#x20;
* The `fail` is a closure/lambda or UDF that will execute if the permissions DID not validate, much like an else statement

Both closures/functions takes in a `user` which is the currently authenticated user, the called in `permissions` and can return anything.

```javascript
// Lambda approach
( user, permissions ) => { 
    // your code here
};
// UDF/Closure
function( user, permissions ){ 
    // your code here
}
```

You can also chain the `when()` calls if needed, to create beautiful security contexts. So if we go back to our admin examples, we can do something like this:

```javascript
var oAuthor = authorService.getOrFail( rc.authorId );
prc.data = userService.getData();

// Run Security Contexts
cbSecure()
    // Only user admin can change to the incoming role
    .when( "USER_ADMIN", ( user ) => oAuthor.setRole( roleService.get( rc.roleID ) ) )
    // The system admin can set a super admin
    .when( "SYSTEM_ADMIN", ( user ) => oAuthor.setRole( roleService.getSystemAdmin() ) )
    // Filter the data to be shown to the user
    .when( "USER_READ_ONLY", ( user ) => prc.data.filter( ( i ) => !i.isClassified ) )

// Calling with a fail closure
cbSecurity.when(
    "USER_ADMIN",
    ( user ) => user.setRole( "admin" ), //success
    ( user ) => relocate( "Invaliduser" ) //fail
);
```

We have also added the following `whenX()` methods to serve your needs when evaluating the permissions:

```javascript
// When all permissions must exist in the user
whenAll( permissoins, success, fail)
// When none of the permissions exist in the user
whenNone( permissions, success, fail )
```


# Verification Methods

If you just want to validate if a user has certain permissions or maybe no permissions at all or if a passed user is the same as the logged in user, then you can use the following boolean methods that only do verification.

{% hint style="success" %}
Please note that you could potentially do these type of methods by leveraging the currently logged in user and it's `hasPermission()` method. However, these methods provide abstraction and can easily be mocked!
{% endhint %}

```javascript
// Checks the user has one or at least one permission if the 
// permission is a list or array
boolean cbSecurity.has( permission );
// The user must have ALL the permissions
boolean cbSecurity.all( permission );
// The user must NOT have any of the permissions
boolean cbSecurity.none( permission );
// Verify if the passed in user is the same as the logged in user
boolean cbSecurity.sameUser( user );
```

These are great to have a unified and abstracted way to verifying permissions or if the passed user is the same as the logged in user. Here are some examples:

**View Layer**

```markup
<cfif cbsecure().has( "USER_ADMIN" )>
    This is only visible to user admins!
</cfif>

<cfif cbsecure().has( "SYSTEM_ADMIN" )>
    <a href="/user/impersonate/#prc.user.getId()#">Impersonate User</a>
</cfif>

<cfif cbsecure().sameUser( prc.user )>
    <i class="fa fa-star">This is You!</i>
</cfif>
```

Other Layers:

```javascript
if( cbSecurity.has( "PERM" ) ){
    auditUser();
}

if( cbSecurity.sameUser( prc.incomingUser ) ){
    // you can change your gravatar
}
```

{% hint style="info" %}
Please note that we do user equality by calling the `getId()` method of the authenticated user and the incoming user. This is part of our `IAuthUser` interface requirements.
{% endhint %}


# Authorization Contexts

There are also times where you need to validate custom conditions and block access to certain areas. This way, you can implement your own custom security logic and leverage **cbSecurity** for blockage. You will accomplish this via the `secureWhen()` method:

```javascript
secureWhen( context, [errorMessage] )
```

The `context` can be a closure/lambda/udf or a boolean evaluation:

```javascript
// Using as a closure/lambda
cbSecurity.secureWhen( ( user ) => !user.isConfirmed() )
cbSecurity.secureWhen( ( user ) => !oEntry.canPublish( user ) )

// Using a boolean evaluation
cbSecurity.secureWhen( cbSecurity.none( "AUTHOR_ADMIN" ) && !cbSecurity.sameUser( oAuthor )  )
cbSecurity.whenNone( "AUTHOR_ADMIN", ( user ) => relocate() );
```

The closure/udf will receive the currently authenticated user as the first argument.

```javascript
( user ) => {}
function( user );
```


# Securing Views

You can also use our handy `event.secureView()` method in the request context to pivot between views according to user permissions.

{% hint style="info" %}
cbSecurity injects the `secureView()` method into the request context via the `preProcess` interception point.
{% endhint %}

```javascript
event.secureView( permissions, successView, failView )
```

This will allow you to set the `successView` if the user has the permissions or the `failView` if they don't.


# Cross Site Request Forgery

This feature set is provided by the cbcsrf module.

Since version 2.4.x we have added the `cbcsrf` module as a dependency of **cbSecurity**.  Below is how you can use it:

## Settings

Below are the settings you can use for this module. Remember you must create the `cbcsrf` struct in your `ColdBox.cfc` under the `moduleSettings` structure:

```javascript
moduleSettings = {
    cbcsrf : {
        // 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 : false
    }
};
```

## Mixins

This module will add the following UDF mixins to handlers, interceptors, layouts and views:

* `csrfToken()` : To generate a token, using the `default` or a custom key
* `csrfVerify()` : Verify a valid token or not
* `csrf()` : To generate a hidden field (`csrf`) with the token
* `csrfField()` : Generate a random token in a hidden form element and javascript that will refresh the page automatically when the token expires
* `csrfRotate()` : To wipe and rotate the tokens for the user

Here are the method signatures:

```javascript
/**
 * Provides a random token and stores it in the coldbox cache storages. You can also provide a specific key to store.
 *
 * @key A random token is generated for the key provided.
 * @forceNew If set to true, a new token is generated every time the function is called. If false, in case a token exists for the key, the same key is returned.
 *
 * @return csrf token
 */
string function csrfToken( string key='', boolean forceNew=false )

/**
 * Validates the given token against the same stored in the session for a specific key.
 *
 * @token Token that to be validated against the token stored in the session.
 * @key The key against which the token be searched.
 *
 * @return Valid or Invalid Token
 */
boolean function csrfVerify( required string token='', string key='' )

/**
 * Generate a random token and build a hidden form element so you can submit it with your form
 *
 * @key A random token is generated for the key provided.
 * @forceNew If set to true, a new token is generated every time the function is called. If false, in case a token exists for the key, the same key is returned.
 *
 * @return HTML of the hidden field (csrf)
 */
string function csrf( string key='', boolean forceNew=false )

/**
 * Generate a random token in a hidden form element and javascript that will refresh the page automatically when the token expires
 * 
 * @key A random token is generated for the key provided. CFID is the default
 * @forceNew If set to true, a new token is generated every time the function is called. If false, in case a token exists for the key, the same key is returned.
 *
 * @return HTML of the hidden field (csrf)
 */
string function csrfField( string key='', boolean forceNew=false )

/**
 * Clears out all csrf token stored
 */
function csrfRotate()
```

## Mappings

The module also registers the following mapping in WireBox: `@cbcsrf` so you can call our service model directly.

```java
component{

    property name="cbcsrf" inject="@cbcsrf";
    
}
```

## Automatic Token Expiration

By default, the module is configured to rotate all user csrf tokens **every 30 minutes**. This means that every token that gets created has a maximum life-span of `{rotationTimeout}` minutes. If you do NOT want the tokens to EVER expire during the user's logged in session, then use the value of `0` zero.

> It is recommended to rotate your keys often, in case your token get's compromised.

## Token Rotation

We have provided several methods to rotate or clear out all of a user's tokens. If you are using `cbAuth` as your module of choice for authentication, then we will listen to **logins** and **logouts** and rotate the keys for you if you have enabled the `enableAuthTokenRotator` setting.

```javascript
moduleSettings = {
    cbcsrf : {
			// Enable/Disable the cbAuth login/logout listener in order to rotate keys
			enableAuthTokenRotator : true
    }
};
```

If you are NOT using `cbAuth` then we recommend you leverage the `csrfRotate()` mixin or the `cbsrf.rotate()` method on the `@cbsrf` model and do the manual rotation yourself.

{% code title="handlers/security.cfc" %}

```javascript
component{

    function doLogin( event, rc, prc ){
    
        if( valid login ){
            // login user
            csrfRotate();
        }
    }
    
    function logout( event, rc, prc  ){
        csrfRotate();
    }

}
```

{% endcode %}

### Simple Example

Below is a simple example of manually verifying tokens in your handlers:

{% code title="registration.cfc" %}

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

     function signUp( event, rc, prc ){
        // Store this in a hidden field in the form
        prc.token = csrfGenerate();
        event.setView( "registration/signup" );
    }

     function signUpProcess( event, rc, prc ){
        // Verify CSFR token from form
        if( csrfVerify( rc.token ?: '' ) {
            // save form
        } else {
            // Something isn't right
            relocate( 'handler.signup' );
        }
    }
}
```

{% endcode %}

## Automatic Token Verifier

We have included an interceptor that if loaded will verify all incoming requests to make sure the token has been passed or it will throw an exception.

The settings for this feature are:

```javascript
cbcsrf : {
    // Enable the verifier
    enableAutoVerifier : true,
    
    // A list of events to exclude from csrf verification, regex allowed: e.g. stripe\..*
    verifyExcludes : [
    
    ]
}
```

You can also register an array of regular expressions that will be tested against the incoming event and if matched, it will allow the request through with no verification.

The verification process is as follows:

* If we are doing an integration test, then skip verification
* If the incoming HTTP Method is a `get,options or head` skip verification
* If the incoming event matches any of the `verifyExcludes` setting, then skip verification
* If the action is marked with a `skipCsrf` annotation, then skip verification
* If no `rc.csrf` exists and no `x-csrf-token` header exists, throw a&#x20;

  `TokenNotFoundException` exception
* If the token is invalid then throw a `TokenMismatchException` exception

Please note that this verifier will check the following locations for the token:

1. The request collection (`rc`) via the `cbcsrf` key
2. The request HTTP header (`x-csrf-token`) key

### `skipCsrf` Annotation

You can also annotate your event handler actions with a `skipCsrf` annotation and the verifier will also skip the verification process for those actions.

```javascript
component{

    function doTestSave( event, rc, prc ) skipCsrf{


    }

}
```

## `/cbcsrf/generate` Endpoint

This module also allows you to turn on the generation HTTP endpoint via the `enableEndpoint` boolean setting. When turned on the module will register the following route: `GET /cbcsrf/generate/:key?`. You can use this endpoint to generate tokens for your users via AJAX or UI only applications. Please note that you can pass an optional `/:key` URL parameter that will generate the token for that specific key.

This endpoint should be secured, so we have annotated it with a `secured` annotation so if you are using `cbSecurity` or `cbGuard` this endpoint will only be available to logged in users.


# CBAuth Validator

ColdBox security ships with the **cbauth** validator that knows how to talk to the authentication service and validate authentication and authorization via permissions.  All you need to do is use the WireBox ID of `CBAuthValidator@cbsecurity` in your `validator` setting:

```javascript
cbsecurity = {

    validator = "CBAuthValidator@cbsecurity"

}
```

{% hint style="info" %}
**CBAuthValidator** is the default validator for ColdBox Security
{% endhint %}

Just make sure your User object adheres to our interface of [IAuthUser](/v2.x-3/usage/authentication-services#user-interface).


# CFML Security Validator

ColdBox security has had this security validator since version 1, in which it will talk to the ColdFusion engine's security methods to authenticate and authorize users.  With it you will be able to authenticate users and also do **role** base authorization.

All you need to do is use the WireBox ID of `CFValidator@cbsecurity` in your `validator` setting:

```javascript
cbsecurity = {

    validator = "CFValidator@cbsecurity"

}
```

{% hint style="info" %}
The default value is of `CFValidator@cbsecurity` which is the WireBox ID for the object.
{% endhint %}

The code for this validator can be found at `cbsecurity.models.CFValidator`

{% embed url="<https://helpx.adobe.com/coldfusion/developing-applications/developing-cfml-applications/securing-applications/using-coldfusion-security-tags-and-functions.html>" %}

## ColdFusion Security Functions

| [cflogin](https://wikidocs.adobe.com/wiki/display/coldfusionen/cflogin)                   | A container for user authentication and login code. The body of the tag runs only if the user is not logged in. When using application-based security, you place code in the body of the cflogin tag to check the user-provided ID and password against a data source, LDAP directory, or other repository of login identification. The body of the tag includes a cfloginuser tag (or a ColdFusion page that contains a cfloginuser tag) to establish the authenticated user's identity in ColdFusion.                                                               |
| ----------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [cfloginuser](https://wikidocs.adobe.com/wiki/display/coldfusionen/cfloginuser)           | Identifies (logs in) a user to ColdFusion. Specifies the user's ID, password, and roles. This tag is typically used inside a cflogin tag. The cfloginuser tag requires three attributes, name, password, and roles, and does not have a body. The roles attribute is a comma-delimited list of role identifiers to which the logged-in user belongs. All spaces in the list are treated as part of the role names, so you should not follow commas with spaces.While the user is logged-in to ColdFusion, security functions access the user ID and role information. |
| [cflogout](https://wikidocs.adobe.com/wiki/display/coldfusionen/cflogout)                 | Logs out the current user. Removes knowledge of the user ID and roles from the server. If you do not use this tag, the user is automatically logged out as described in *Logging out users* in [Using ColdFusion security tags and functions](https://wikidocs.adobe.com/wiki/display/coldfusionen/Using+ColdFusion+security+tags+and+functions).The cflogout tag does not take any attributes, and does not have a body.                                                                                                                                             |
| [cfNTauthenticate](https://wikidocs.adobe.com/wiki/display/coldfusionen/cfNTauthenticate) | Authenticates a user name and password against the NT domain on which ColdFusion server is running, and optionally retrieves the user's groups.                                                                                                                                                                                                                                                                                                                                                                                                                       |
| [cffunction](https://wikidocs.adobe.com/wiki/display/coldfusionen/cffunction)             | If you include a roles attribute, the function executes only when there is a logged-in user who belongs to one of the specified roles.                                                                                                                                                                                                                                                                                                                                                                                                                                |
| [IsUserInAnyRole](https://wikidocs.adobe.com/wiki/display/coldfusionen/IsUserInAnyRole)   | Returns True if the current user is a member of the specified role.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| [GetAuthUser](https://wikidocs.adobe.com/wiki/display/coldfusionen/GetAuthUser)           | Returns the ID of the currently logged-in user.This tag first checks for a login made with cfloginuser tag. If none exists, it checks for a web server login (cgi.remote\_user.                                                                                                                                                                                                                                                                                                                                                                                       |

### Example:

{% code title="handlers/security.cfc" %}

```javascript
component{

	function login( event, rc, prc ){
		event.setView( "security/login" );
	}
	
	function doLogin( event, rc, prc ){
		cflogin(
			idletimeout=getSetting( "LoginTimeout" ), 
			applicationtoken=getSetting( "AppName" ), 
			cookiedomain='myapp.com'
		){
			cfoauth(
				type        = "Google",
				clientid    = "YOUR_CLIENT_ID",
				secretkey   = "YOUR_GOOGLE_CLIENTSECRET",
				redirecturi = "YOUR_CALLBACK_URI",
				result      = "res",
				scope       = "YOUR_SCOPES",
				state       = "cftoken=#cftoken#"
			);

			cfloginuser(
				name     = "#res.other.email#", 
				password = "#res.access_token#", 
				roles    = "user"
			);
		}
	}
	 
	function doLogout( event, rc, prc ){
	   
	    cflogout();
	 	relocate( "security.login" );
	}

}
```

{% endcode %}

For more information about `cflogin, cfloginuser and cflogout`, please visit the docs <http://cfdocs.org/security-functions>


# Custom Validator

## Registration

In order to register your own custom security validator just open the `config/Coldbox.cfc` and add the `validator` key with the value being a WireBox ID that points to your object that will provide the validation.

{% code title="config/Coldbox.cfc" %}

```javascript
moduleSettings = {
    cbSecurity = {
         validator = "SecurityService"   
    }
}
```

{% endcode %}

## Validator Interface

A security validator object is a simple CFC that implements the following functions

{% code title="cbsecurity/interfaces/IUserValidator.cfc" %}

```javascript
/**
 * Copyright since 2016 by Ortus Solutions, Corp
 * www.ortussolutions.com
 * ---
 * All security validators must implement the following methods
 */
interface{

	/**
	 * This function is called once an incoming event matches a security rule.
	 * You will receive the security rule that matched and an instance of the ColdBox controller.
	 *
	 * You must return a struct with two keys:
	 * - allow:boolean True, user can continue access, false, invalid access actions will ensue
	 * - type:string(authentication|authorization) The type of block that ocurred.  Either an authentication or an authorization issue.
	 *
	 * @return { allow:boolean, type:string(authentication|authorization) }
	 */
	struct function ruleValidator( required rule, required controller );

	/**
	 * This function is called once access to a handler/action is detected.
	 * You will receive the secured annotation value and an instance of the ColdBox Controller
	 *
	 * You must return a struct with two keys:
	 * - allow:boolean True, user can continue access, false, invalid access actions will ensue
	 * - type:string(authentication|authorization) The type of block that ocurred.  Either an authentication or an authorization issue.
	 *
	 * @return { allow:boolean, type:string(authentication|authorization) }
	 */
	struct function annotationValidator( required securedValue, required controller );

}
```

{% endcode %}

Each validator must return a **struct** with the following keys:

* `allow:boolean` A Boolean indicator if authentication or authorization was violated
* `type:stringOf(authentication|authorization)` A string that indicates the type of violation: authentication or authorization.

## Example

Here is a sample validator using permission based security in both rules and annotation context

{% code title="models/SecurityService.cfc" %}

```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;
}
```

{% endcode %}

That's it!  Go validate!


# JWT Services

CBSecurity also provides you with a JWT (Json Web Tokens) authentication and authorization system.

JSON Web Token (JWT) is an open standard ([RFC 7519](https://tools.ietf.org/html/rfc7519)) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the **HMAC** algorithm) or a public/private key pair using **RSA** or **ECDSA**.

![](/files/-LpZaYKa3vFWDHA_EpPt)

Signed tokens can verify the *integrity* of the **claims** contained within it, while encrypted tokens *hide* those claims from other parties. When tokens are signed using public/private key pairs, the signature also certifies that only the party holding the private key is the one that signed it.

![](/files/-LpZaLsJhjTiD7hZRuxv)

You can find much more information about JWT at [jwt.io](https://jwt.io/introduction/).

{% embed url="<https://jwt.io/introduction/>" %}

## When should you use JSON Web Tokens?

JSON Web Tokens have become the standard for authenticating and authorizing API requests. They can be used on their own or with an oauth/single sign-on server as well.

* **Authorization**: This is the most common scenario for using JWT. Once the user is logged in, each subsequent request will include the JWT, allowing the user to access routes, services, and resources that are permitted with that token.
* **Information Exchange**: JSON Web Tokens are a good way of securely transmitting information between parties. Because JWTs can be signed—for example, using public/private key pairs—you can be sure the senders are who they say they are. Additionally, as the signature is calculated using the header and the payload, you can also verify that the content hasn't been tampered with.

The ColdBox Security module will assist you with all the generation, decoding, encoding and security aspects of JWT. All you need to do is, configure it, create a few standard files and off you go.

## Tokens

The tokens created by the JWT services will have the mandatory headers, but also will have a standardizes payload structure. This payload structure can also be customized as you see fit.

![](/files/-LpZ_IOoDCwfxZUXGi5a)

A JSON Web Token encodes a series of claims in a JSON object. Some of these claims have specific meaning, while others are left to be interpreted by the users. You can consider claims to be the keys of the payload structure and it can contain, well, pretty much anything you like.

### Base Claims

Here are the base claims that the ColdBox Security JWT token creates for you automatically:

* Issuer (`iss`) - The issuer of the token (defaults to the application's base URL)
* Issued At (`iat`) - When the token was issued (unix timestamp)
* Subject (`sub`) - This holds the identifier for the token (defaults to user id)
* Expiration time (`exp`) - The token expiry date (unix timestamp)
* Unique ID (`jti`) - A unique identifier for the token (md5 of the sub and iat claims)
* Scopes (`scope)` - A space delimited string of scopes attached to the token
* Refresh Token (`cbsecurity_refresh` ) - If you are using refresh tokens, this custom claim will be added to the payload.

{% code title="mytoken.json" %}

```javascript
{
  "iat": 1569340662,
  "scope": "",
  "iss": "http://127.0.0.1:56596/",
  "sub": 123,
  "exp": 1569344262,
  "jti": "12954F907C0535ABE97F761829C6BD11"
}
```

{% endcode %}

{% code title="myRefreshToken.json" %}

```javascript
{
  "iat": 1569340662,
  "scope": "",
  "iss": "http://127.0.0.1:56596/",
  "sub": 2222,
  "exp": 1569344262,
  "jti": "234234CDDEEDD",
  "cbsecurity_refresh" : true
}
```

{% endcode %}

You can add much more to this payload via the JWT service methods or via the User that models the token.

## Our JwtService

The service can be found here `cbsecurity.models.JWTService` and can be retrieved by either injecting the service (`JwtService@cbsecurity`) or using our helper method (`jwtAuth()`).

```javascript
// Injection
property name="jwtService" inject="JwtService@cbsecurity";

// Helper Method in any handler/layout/interceptors/views
jwtAuth()
```

In order to begin exploring the JWT capabilities, let's explore how to configure it first.

## Configuration

Our JWT services have several configuration settings, let's explore them:

```javascript
cbsecurity : {
    // The WireBox ID of the authentication service to use in cbSecurity which must adhere to the cbsecurity.interfaces.IAuthService interface.
    authenticationService  : "authenticationService@cbauth",
    // WireBox ID of the user service to use
    userService             : "",
    // The name of the variable to use to store an authenticated user in prc scope if using a validator that supports it.
    prcUserVariable         : "oCurrentUser",
    // JWT Settings
    jwt                     : {
        // The issuer authority for the tokens, placed in the `iss` claim
        issuer                          : "",
        // The jwt secret encoding key, defaults to getSystemEnv( "JWT_SECRET", "" )
        // This key is only effective within the `config/Coldbox.cfc`. Specifying within a module does nothing.
        secretKey               : getSystemSetting( "JWT_SECRET", "" ),
        // by default it uses the authorization bearer header, but you can also pass a custom one as well.
        customAuthHeader        : "x-auth-token",
        // The expiration in minutes for the jwt tokens
        expiration              : 60, 
        // If true, enables refresh tokens, token creation methods will return a struct instead
        // of just the access token. e.g. { access_token: "", refresh_token : "" }
        enableRefreshTokens        : false,
        // The default expiration for refresh tokens, defaults to 30 days
        refreshExpiration          : 10080,
        // The Custom header to inspect for refresh tokens
        customRefreshHeader        : "x-refresh-token",
        // If enabled, the JWT validator will inspect the request for refresh tokens and expired access tokens
        // It will then automatically refresh them for you and return them back as
        // response headers in the same request according to the customRefreshHeader and customAuthHeader
        enableAutoRefreshValidator : false,
        // Enable the POST > /cbsecurity/refreshtoken API endpoint
        enableRefreshEndpoint      : true,
        // encryption algorithm to use, valid algorithms are: HS256, HS384, and HS512
        algorithm               : "HS512",
        // Which claims neds to be present on the jwt token or `TokenInvalidException` upon verification and decoding
        requiredClaims          : [] ,
        // The token storage settings
        tokenStorage            : {
            // enable or not, default is true
            "enabled"       : true
            // A cache key prefix to use when storing the tokens
            "keyPrefix"     : "cbjwt_", 
            // The driver to use: db, cachebox or a WireBox ID
            "driver"        : "cachebox",
            // Driver specific properties
            "properties"    : {
                cacheName : "default"
            }
        }
    }
}
```

### Authentication Service

The WireBox Id of the service to provide our authentication. **cbauth** is our default provider, but you can use any authentication service that [adheres to our interface](/v2.x-3/usage/authentication-services).

### User Service

The WireBox Id of the service to provide our user retrieval and validation functions. You can use any service that [adheres to our interface](/v2.x-3/usage/authentication-services).

### prcUserVariable

The default variable name in the `prc` scope that will be used to store an authenticated user object if the JWT request is valid. The default is `prc.oCurrentUser`

### issuer

The issuer authority for the tokens, placed in the `iss` claim of the token. If empty, we will use the `event.buildLink()` to create the issuer. By default, our validators also check that tokens are created by the same issuer.

### secretKey

The secret key is used to sign the JWT tokens. By default it will try to load an environment variable called `JWT_SECRET` , if that setting is also empty, then we will auto-generate a secret token that will last as long as the ColdFusion application scope lasts. So technically, your secret will rotate only if a secret is not specified.

Also, this key is ignored in modules. To specify a fixed key to be used in your modules, you will have to configure it by adding a cbsecurity key settings in the moduleSettings structure within the config/Coldbox.cfc.

{% hint style="success" %}
Your secret key will auto-rotate every application scope rotation. Please note that all tokens used after that scope rotation will automatically become invalid.

Please note that we use the jwt-cfml library for encoding/decoding tokens. Please [refer to it's documentation](https://forgebox.io/view/jwt-cfml) in order to leverage RS and ES algorithms with certificates.

<https://forgebox.io/view/jwt-cfml>
{% endhint %}

### customAuthHeader

By default, our jwt services will look into the `authorization` header for a bearer token. However, it can also look in a custom header by this name, which defaults to `x-auth-token`. Finally, if not found, it will also look into the `rc` scope for a `rc[ 'x-auth-token' ]` as well.

### Expiration

The default expiration in minutes for the JWT tokens. Defaults to 60 minutes

### Algorithm

The encryption algorithm to use for the tokens. The default is **HS512**, but the available ones for are:

* HS256
* HS384
* **HS512**
* RS256
* RS384
* RS512
* ES256
* ES384
* ES512

In the case of the `RS` and `ES` algorithms, asymmetric keys are expected to be provided in unencrypted PEM or JWK format (in the latter case first deserialize the JWK to a CFML struct). When using PEM, private keys need to be encoded in PKCS#8 format.

If your private key is not currently in this format, conversion should be straightforward:

```
$ openssl pkcs8 -topk8 -nocrypt -in privatekey.pem -out privatekey.pk8
```

When decoding tokens, either a public key or certificate can be provided. (If a certificate is provided, the public key will be extracted from it.)

{% embed url="<https://forgebox.io/view/jwt-cfml>" %}

### RequiredClaims

This is an array of claim names that each token MUST have in order to be authenticated. If a token comes in but does not have these claims in the payload structure, it will be deemed invalid.

### Token Storage

By default, our JWT services will store tokens in CacheBox for you in order to be able to invalidate them. We ship with two providers for token storage: db and cachebox.

#### Enabled

By default the token storage is enabled.

#### KeyPrefix

The key prefix to use when storing the keys in the permanent storage. Defaults to `cbjwt_`

#### Driver

The driver to use. Can be either **db** or **cachebox** or your own WireBox Id for using a custom storage.

#### Properties

A struct of properties to configure each storage with.

### Refresh Token Configuration

Refresh tokens have several configuration items, check them out in our [refresh token configuration section](/v2.x-3/jwt/refresh-tokens#refresh-token-configuration).

## JWT Subject Interface

The next step is to make sure that our JWT services can handle the construction of the JWT tokens as per YOUR requirements. So your `User` object must implement our `JWTSubject` interface with the following functions:

{% code title="cbsecurity.interfaces.jwt.IJwtSubject.cfc" %}

```javascript
/**
 * Copyright since 2016 by Ortus Solutions, Corp
 * www.ortussolutions.com
 * ---
 * If you use the jwt services, then your jwt subject user must implement this interface
 */
interface{

    /**
     * A struct of custom claims to add to the JWT token when creating it
	 *
	 * @payload The actual payload structure that was used in the request
	 *
	 * @return A structure of custom claims
     */
    struct function getJwtCustomClaims( required struct payload );

    /**
     * This function returns an array of all the scopes that should be attached to the JWT token that will be used for authorization.
     */
    array function getJwtScopes();

}

```

{% endcode %}

Basically, it's two functions:

* `getJwtCustomClaims( payload )` - This is a struct of custom claims to incorporate into the token payload at construction time. This can be ANYTHING you like.
* `getJwtScopes()` - We will also call this at construction time in order to incorporate the right permission scopes into the token according to your user. This must be an array of scopes/permissions.

Since also the authentication services will be used with JWT, your user object might end up looking like this:

{% code title="models/User.cfc" %}

```javascript
component accessors="true" {

    property name="auth" inject="authenticationService@cbauth";

    property name="id";
    property name="firstName";
    property name="lastName";
    property name="username";
    property name="password";

    function init(){
        variables.id        = "";
        variables.firstName = "";
        variables.lastName  = "";
        variables.username  = "";
        variables.password  = "";

        variables.permissions = [ "write", "read" ];

        return this;
    }

    boolean function isLoaded(){
        return ( !isNull( variables.id ) && len( variables.id ) );
    }

    /**
     * A struct of custom claims to add to the JWT token
     */
    struct function getJWTCustomClaims(){
        return { "role" : "admin" };
    }

    /**
     * This function returns an array of all the scopes that should be attached to the JWT token that will be used for authorization.
     */
    array function getJWTScopes(){
        return variables.permissions;
    }

    /**
     * Verify if the user has one or more of the passed in permissions
     *
     * @permission One or a list of permissions to check for access
     *
     */
    boolean function hasPermission( required permission ){
        if ( isSimpleValue( arguments.permission ) ) {
            arguments.permission = listToArray( arguments.permission );
        }

        return arguments.permission
            .filter( function(item){
                return ( variables.permissions.ListFindNoCase( item ) );
            } )
            .len();
    }

}
```

{% endcode %}

## Authentication and User Services

Please note that the JWT validators must talk to the authentication and user services. Please refer to the [Authentication Services](/v2.x-3/usage/authentication-services) page to configure and create them.

## JWT Methods

Ok, now we can focus on all the wonderful methods the JWT service offers:

### Token Creation Methods

* `attempt( username, password, [ customClaims:struct ] ):token` - Attempt to authenticate a user with the authentication service and if successful, return the token using the identifier and custom claims. Exception if invalid authentication
* `fromUser( user, [ customClaims:struct ] ):token` - Generate a token according to the passed user object and custom claims.

### Raw JWT Methods

* `encode( struct payload ):token` - Generate a raw jwt token from a native payload struct.
* `verify( required token ):boolean` - Verify a token string or throws exception
* `decode( required token ):struct` - Decode and retrieve the passed in token to CFML struct

### Parsing and Helper Methods

* `parseToken( token, storeInContext, authenticate ):struct` - Get the decoded token using the headers strategy and store it in the `prc.jwt_token` and the decoded data as `prc.jwt_payload` if it verifies correctly. Throws: `TokenExpiredException` if the token is expired, `TokenInvalidException` if the token doesn't verify decoding, `TokenNotFoundException` if not found
* `getToken():string` - Get the stored token from `prc.jwt_token`, if it doesn't exist, it tries to parse it via `parseToken()`, if not token is set this will be an empty string.
* `getPayload():struct` - Get the stored token from `prc.jwt_payload`, if it doesn't exist, it tries to parse it via `parseToken()`, if not token is set this will be an empty struct.
* `setToken( token ):JWTService` - Store the token in `prc.jwt_token`, and store the decoded version in `prc.jwt_payload`

### Authentication Helpers

* `authenticate( [payload] ):User` - Authenticates a passed or detected token payload and return the user it represents
* `getuser()` - Get the authenticated user according to the access token detected
* `logout()` - Logout a user and invalidate their token

### Storage Methods

* `invalidateAll( async:false )` - Invalidate all access and refresh tokens in permanent storage
* `invalidate( token )` - Invalidates the incoming token by removing it from the permanent storage.
* `isTokenInStorage( token )` - Checks if the passed token exists in permanent storage.
* `getTokenStorage( force:false )` - Get the current token storage implementation. You can also force create it again if needed.

### Refresh Methods

* `attempt( username, password, [ customClaims:struct ] ):struct` - Attempt to authenticate a user with the authentication service and if successful, return a struct containing an access and refresh token.
* `fromUser( user, [ customClaims:struct ] ):struct` - Generate a struct of refresh and access token according to the passed user object and custom claims.

```javascript
{
    "access_token"  : "AYjcyMzY3ZDhiNmJk",
    "refresh_token" : "RjY2NjM5NzA2OWJj"
}
```

## Putting it Together

That's it, we are ready to put it all together. Now cbsecurity knows about your authentication/user services, can talk to your user to create tokens and can guard the incoming requests via the JWT Validator. Here is a sample controller for login, logout and user registration:

Let's configure some routes first:

```javascript
post( "/api/login" , "api.auth.login" );
post( "/api/logout" , "api.auth.logout" );
post( "/api/register" , "api.auth.register" );
```

Then build out the `Auth` controller

```javascript
component{

    function login( event, rc, prc ){
        param rc.username = "";
        param rc.password = "";

        try {
            var token = jwtAuth().attempt( rc.username, rc.password );
            return {
                "error"   : false,
                "data"    : token,
                "message" : "Bearer token created and it expires in #jwtAuth().getSettings().jwt.expiration# minutes"
            };
        } catch ( "InvalidCredentials" e ) {
            event.setHTTPHeader( statusCode = 401, statusText = "Unauthorized" );
            return { "error" : true, "data" : "", "message" : "Invalid Credentials" };
        }
    }

    function register( event, rc, prc ){
        param rc.firstName = "";
        param rc.lastName  = "";
        param rc.username  = "";
        param rc.password  = "";

        prc.oUser = populateModel( "User" );
        userService.create( prc.oUser );

        var token = jwtAuth().fromuser( prc.oUser );
        return {
            "error"   : false,
            "data"    : token,
            "message" : "User registered correctly and Bearer token created and it expires in #jwtAuth().getSettings().jwt.expiration# minutes"
        };
    }

    function logout( event, rc, prc ){
        jwtAuth().logout();
        return { "error" : false, "data" : "", "message" : "Successfully logged out" };
    }
}
```

{% hint style="danger" %}
Make sure you add validation!
{% endhint %}

That's it, we now can login a user, give them a token, register a new user and give them their token, and also log them out. The next step is for you to build your rules and/or security annotations and make sure the [JWT validator ](/v2.x-3/jwt/jwt-validator)is configured for your global app or module.

## Web Server Configuration

In order to implement JWT authentication in your application, you may need to modify some web server settings. Most web servers have default content length restrictions on the size of an individual header. If your web server platform has such default enabled, you will need to increase the buffer size to accommodate the presence of JTW tokens in both the request and response headers. The size of a JWT token header, encrypted via the default cbSecurity HMAC512 algorithm, is around 44 kilobytes. As such you will need to allow for at least that size. Below are some examples for common web server configurations

### NGINX

The following configuration may be applied to the main NGINX `http` configuration block to allow for the presence of tokens in both the request and response headers:

```julia
http {
    # These settings affect outbound headers via proxy server
    proxy_buffer_size   64k;
    proxy_buffers   4 128k;
    proxy_busy_buffers_size   128k;
    # These settings affect the http client request headers
    client_body_buffer_size     128k;
    client_header_buffer_size   64k;
    large_client_header_buffers 8 128k;
    # These settings affect HTTP/2 headers, however some versions of NGINX will throw an error on HTTP/1 requests if these are not present
    http2_max_header_size 128k;
    http2_max_field_size 1000m;
}
```

### IIS

You will need to modify two registry keys:

1. `HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\HTTP\Parameters\MaxFieldLength` - Sets an upper limit, in bytes, for each header. The default value is 65534 bytes and the maximum value is 65534 bytes ( 64kb )
2. `HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\HTTP\Parameters\MaxRequestBytes` - Sets the upper limit for the request line and the headers, combined. As such 128K should allow for both long URLs, as well as JWT tokens in the headers. The default value is 16384 bytes and the maximum value is 16777216 bytes ( 16 MB )

### Apache

You will need to add a `LimitRequestFieldSize` setting in each `<VirtualHost...>` entry in order increase the default header size from the default 8 kilobytes. Example, with a setting of 128 kilobytes:

```markup
<VirtualHost 10.10.50.50:80>
    ServerName www.mysite.com

    LimitRequestFieldSize 128000

    RewriteEngine On
    ...
    ...
</VirtualHost>
```


# JWT Validator

Now that we have all the pieces in place for JWT, we can now register the JWT validator as our validator of choice for requests which in our case it is the same JWT Service that will take care of the validation: `JWTService@cbsecurity`.&#x20;

The validator will inspect the incoming requests for valid jwt authorization headers. It will be in charge of verifying their expiration, their required claims, and the user it represents. Once that is done, it goes in the same rule/annotation security flow that **cbsecurity** leverages.

{% code title="config/Coldbox.cfc" %}

```javascript
cbsecurity = {
    validator = "JWTService@cbsecurity"
}
```

{% endcode %}

## Module Override

Each module can also override their validator via it's configuration setting `cbsecurity.validator`. So if the global validator is something other than jwt but your module REQUIRES JWT validation, then just add it in your `ModuleConfig.cfc`

```javascript
settings = {
    cbsecurity = {
         validator = "JWTService@cbsecurity"
    }
}
```

## JWT Token Discovery

The JWT validator will discover the incoming JWT token from 3 sources:

1. `authorization` header using the bearer token approach
2. Custom header configured in your settings: `cbsecurity.customAuthHeader`
3. Incoming `rc` variable with the same name as `cbsecurity.customAuthHeader`

## Token Scopes & Permissions

If your rules have the `permissions` element or your `secure` annotations have context, then we will treat those as the scopes/permissions to check the user/token must have at validation.

{% embed url="<https://auth0.com/docs/scopes/current>" %}

## Validator Process

The validator will have the following validation process:

* Verify the jwt token exists via the `authorization` header or custom header `x-auth-token` or incoming `rc[ 'x-auth-token' ]`
* Verify we can decode it
* Verify if it has not expired from the token itself
  * If you have enabled auto refresh tokens, check out the [refresh tokens process](/v2.x-3/jwt/refresh-tokens#enableautorefreshvalidator).
* Verify it has the required claims
* If token storage is enabled, verify the token in the permanent storage
* Verify the subject (`sub`) claim and try to retrieve the user it represents
* Try to authenticate the user for the request
* Verify the subject has the right permissions or the token has the right scopes attached to it.
* If all is valid then place the token in `prc.jwt_token` and the payload in `prc.jwt_payload`
* If all is valid then place the user object in `prc.oCurrentUser` or the variable of your choice via the `cbsecurity.prcUserVariable` setting.
* Continue or block

That's it!  You can create your rules and annotations just like your used to, but now the validator will make sure valid JWT tokens are passed for those requests.


# Refresh Tokens

ColdBox Security supports the concept of refresh tokens alongside the normal JWT access tokens. Let's start exploring this feature in detail.

## What Is a Refresh Token?

A refresh token is a credential artifact that lets a client application get new access tokens without having to ask the user to log in again. Access tokens may be valid for a short amount of time. Once they expire, client applications can use a refresh token to "**refresh**" the access token.

The client application can get a new access token as long as the refresh token is valid and unexpired. Consequently, a refresh token that has a very long lifespan could theoretically give infinite power to the token bearer to get a new access token to access protected resources anytime. The bearer of the refresh token could be a legitimate user or a malicious user.

### Refresh Token Configuration

In the `jwt` section of the `cbsecurity` configuration you will have the following settings dealing with refresh tokens (Please note that the other jwt configurations are also mandatory)

```javascript
jwt : {

    ...

    // If true, enables refresh tokens, token creation methods will return a struct instead of just an access token string
    // e.g. { access_token: "", refresh_token : "" }
    "enableRefreshTokens"   : false,
    // The default expiration for refresh tokens in minutes, defaults to 7 days
    "refreshExpiration"     : 10080,
    // The custom header to inspect for refresh tokens
    "customRefreshHeader"    : "x-refresh-token",
    // If enabled, the JWT validator will inspect the request for refresh tokens and expired access tokens
    // It will then automatically refresh them for you and return them back as 
    // response headers in the same request according to the `customRefreshHeader` and `customAuthHeader`
    "enableAutoRefreshValidator" : false,
    // Enable the POST > /cbsecurity/refreshtoken API endpoint
    "enableRefreshEndpoint" : false
}
```

#### EnableRefreshTokens

This setting is used to turn on the refresh capabilities of the JWT Service. If this remains false, then exceptions will be thrown when trying to use refresh capabilities.

#### RefreshExpiration

The default time refresh tokens expire in. The default is 7 days or 10080 minutes

#### CustomRefreshHeader

The header to inspect for refresh tokens for automatic refreshment or our refresh endpoints. The default is `x-refresh-token`

#### EnableAutoRefreshValidator

If you enable the auto refresh validator setting, then cbsecurity will try to auto-refresh expired access tokens via the Validator security events. These events fire when a rule is detected or a secured annotation is detected.

#### EnableRefreshEndpoint

If enabled, the REST `cbsecurity/refreshToken` endpoint will be available for the application, so users can refresh their tokens.

## Token Creation

You must enable the setting (`enableRefreshTokens`) in order for the following methods to return a `struct` of tokens. If not, only the access token will be returned as a `string`.

* `attempt( username, password ):struct`
* `fromUser( user, customClaims ):struct`

The returned struct will contain the access and refresh tokens:

```javascript
{
    "access_token"  : "AYjcyMzY3ZDhiNmJk",
    "refresh_token" : "RjY2NjM5NzA2OWJj"
}
```

This is the same procedure for creating access tokens, but now you get a struct of tokens instead of a single access token.

## Refreshing Tokens Manually

You can refresh tokens manually by using the `refreshToken( token, customClaims )` method on the `JwtService` object. You can pass a valid refresh token to be used for refreshment or pass **none** and the token will be inspected from the headers or incoming rc using the `x-refresh-token` value or whatever you setup as your `customRefreshHeader` setting.

```javascript
var newTokens = jwtService.refreshToken();

var newTokens = jwtService.refreshToken( storedRefreshToken );
```

Here is the signature for the refresh method:

```javascript
/**
 * Manually refresh tokens by passing a valid refresh token and returning two new tokens:
 * <code>{ access_token : "", refresh_token : "" }</code>
 *
 * @refreshToken A refresh token
 * @customClaims A struct of custom claims to apply to the new tokens
 *
 * @throws RefreshTokensNotActive If the setting enableRefreshTokens is false
 * @throws TokenExpiredException If the token has expired or no longer in the storage (invalidated)
 * @throws TokenInvalidException If the token doesn't verify decoding
 * @throws TokenNotFoundException If the token cannot be found in the headers
 *
 * @return A struct of { access_token : "", refresh_token : "" }
 */
struct function refreshToken( token = discoverRefreshToken(), struct customClaims = {} )
```

{% hint style="success" %}
`customClaims` where added in v2.15.0
{% endhint %}

{% hint style="danger" %}
**Important:**

Please note that the currently used refresh token will be **invalidated** and **rotated** for you automatically. This is a security feature called **refresh token rotation**, where the refreshed token is automatically rotated for you upon refresh usage.
{% endhint %}

## Refresh Token Endpoint

If you have enabled the refresh token setting (`enableRefreshEndpoint`) then you will also have access to the `POST > /cbsecurity/refreshtoken` API endpoint.

This endpoint is used for applications to refresh their access tokens using the refresh token received when authenticating in the application.

This endpoint must be executed with a `POST` and you will need to pass in your refresh token via the following header: `x-refresh-token` or rc form variable of the same name. If valid, the response `data` will contain two new tokens for you:

```javascript
{
    "access_token" : "AYjcyMzY3ZDhiNmJk",
    "refresh_token" : "RjY2NjM5NzA2OWJj"
}
```

{% hint style="danger" %}
**Important:**

Please note that the currently used refresh token will be **invalidated** and **rotated** for you automatically. This is a security feature called **refresh token rotation**, where the refreshed token is automatically rotated for you upon refresh usage.
{% endhint %}

## Refresh Token Rotation

CBSecurity by default provides you with refresh token rotation every time you want to refresh your access token. This guarantees that every time an application exchanges a refresh token for an access token, a **NEW** refresh token is returned as well. The old refresh token is invalidated and can no longer be used.

Therefore, you no longer have a long-lived refresh token that could provide illegitimate access to resources if it ever becomes compromised or leaked. The threat of unauthorized access is reduced as refresh tokens are continually exchanged and invalidated.

## Refresh Token Header Auto Refreshment

CBSecurity has the ability to refresh access tokens automatically for you when calling any secure resource that is protected by the JWT Validator. All you have to do is send in both tokens via the appropriate headers and enable the `autoRefreshValidator` setting:

* access token
  * bearer token or
  * `x-auth-token`
* refresh token
  * `x-refresh-token`

If the access token has expired or is invalid or missing and the `x-refresh-token` was passed and is valid, then the access token will be re-generated, the refresh token will be rotated, the request will continue as normal and two new **response** headers will be sent back to the calling application.

* `x-auth-token` : refreshed access token
* `x-refresh-token` : new refresh token

The calling application can monitor if those two response headers are sent and save them appropriately.


# Token Storage

You can enable token storage in cbsecurity via the `tokenStorage` setting. By default it is **enabled** and leverages CacheBox's `default` cache using a key prefix of `cbjwt_` + the token's unique identifier claim of `jti`.

{% hint style="danger" %}
We recommend that you create a separate provider for the cache.
{% endhint %}

## Why use a storage?

The storage of keys are great in order to visualize in your application all the registered keys in the system. You can also invalidate keys, as by default if the token does not exist in the storage, it is considered invalid.

You can retrieve the token storage by injection or the helper method:

```javascript
property name="tokenStorage" inject="DBTokenStorage@cbsecurity";
property name="tokenStorage" inject="CacheTokenStorage@cbsecurity";

jwtAuth().getTokenStorage()
```

## Storage Drivers

We ship with two drivers:

* `cachebox` : Leverages any cache registered in CacheBox
* `db` : Leverages a database table to store the keys

### **CacheBox Driver Properties**

* `cacheName` : The cache to use

### **DB Driver Properties**

* `table`   : The table to use for storage
* `schema`  : A schema to use if the database supports it, else empty
* `dns`     : The datasource to use, defaults to the one set in `Application.cfc`
* `autoCreate:true` : Autocreate the table if not found
* `rotationDays:7` : How many days should the expiration be before removal
* `rotationFrequency:60` : How many minutes should pass before issuing a rotation check

The columns it will create are:

* `id` - identifier
* `cacheKey` - The unique cacke key, indexed
* `token` - The encrypted token
* `expiration` - The expiration
* `issued` - The issue date
* `subject` - The subject identifier

## Custom Token Storage

If you would like to create your own token storage, just add your own WireBox ID to the `driver`, `properties` and implement the following interface: `cbsecurity.interfaces.jwt.IJwtStorage`

{% code title="cbsecurity.interfaces.jwt.IJwtStorage.cfc" %}

```javascript
interface{

    /**
     * Configure the storage by passing in the properties
     * 
     * @return JWTStorage
     */
    any function configure( required properties );

    /**
     * Set a token in the storage
     * 
     * @key The cache key
     * @token The token to store
     * @expiration The token expiration
     * 
     * @return JWTStorage
     */
    any function set( required key, required token, required expiration );

    /**
     * Verify if the passed in token key exists
     * 
     * @key The cache key
     */
    boolean function exists( required key );

    /**
     * Retrieve the token via the cache key, if the key doesn't exist a TokenNotFoundException will be thrown
     * 
     * @key The cache key
     * @defaultValue If not found, return a default value
     *
     * @throws TokenNotFoundException
     */
    any function get( required key, defaultValue );

    /**
     * Invalidate/delete one or more keys from the storage
     *
     * @key A cache key or an array of keys to clear
     * 
     * @return JWTStorage
     */
    any function clear( required any key );

    /**
     * Clear all the keys in the storage
     *
     * @async Run in a separate thread
     * 
     * @return JWTStorage
     */
    any function clearAll( boolean async=false );

    /**
     * Retrieve all the jwt keys stored in the storage
     */
    array function keys();

    /**
     * The size of the storage
     */
    numeric function size();

}
```

{% endcode %}


# JWT Interceptions

The JWT Services will announce some key events for you to listen to

* `cbSecurity_onJWTCreation` - Whenever a new token is generated for a user
* `cbSecurity_onJWTInvalidation` - Whenever an invalidation occurs for a token
* `cbSecurity_onJWTValidAuthentication` - Whenever a valid JWT token is parsed, tested and authenticated with the authentication services
* `cbSecurity_onJWTInvalidUser` - When trying to find the token's subject and the user service returns null or not a valid user
* `cbSecurity_onJWTInvalidClaims` - When the parsed token does not adhere to the required claims
* `cbSecurity_onJWTExpiration` - When the parsed token has expired
* `cbSecurity_onJWTStorageRejection` - When the parsed token is valid but cannot be found in the permanent storage
* `cbSecurity_onJWTValidParsing` - When the parsed token has passed all validation procedures but has NOT been authenticated yet.

## cbSecurity\_onJWTCreation

This event has the following data in the `interceptData` struct

| Key       | Description                            |
| --------- | -------------------------------------- |
| `token`   | The JWT token                          |
| `payload` | The payload that was used to create it |
| `user`    | The user it belongs to                 |

## cbSecurity\_onJWTInvalidation

This event has the following data in the `interceptData` struct

| Key     | Description                        |
| ------- | ---------------------------------- |
| `token` | The JWT token that was invalidated |

## cbSecurity\_onJWTValidAuthentication

This event has the following data in the `interceptData` struct

| Key       | Description                   |
| --------- | ----------------------------- |
| `token`   | The JWT token that was parsed |
| `payload` | The payload that was decoded  |
| `user`    | The authenticated user        |

## cbSecurity\_onJWTInvalidUser

This event has the following data in the `interceptData` struct

| Key       | Description                     |
| --------- | ------------------------------- |
| `token`   | The JWT token that was parsed   |
| `payload` | The JWT payload that was parsed |

## cbSecurity\_onJWTInvalidClaims

This event has the following data in the `interceptData` struct

| Key       | Description                     |
| --------- | ------------------------------- |
| `token`   | The JWT token that was parsed   |
| `payload` | The JWT payload that was parsed |

## cbSecurity\_onJWTExpiration

This event has the following data in the `interceptData` struct

| Key       | Description                     |
| --------- | ------------------------------- |
| `token`   | The JWT token that was parsed   |
| `payload` | The JWT payload that was parsed |

## cbSecurity\_onJWTStorageRejection

This event has the following data in the `interceptData` struct

| Key       | Description                     |
| --------- | ------------------------------- |
| `token`   | The JWT token that was parsed   |
| `payload` | The JWT payload that was parsed |

## cbSecurity\_onJWTValidParsing

This event has the following data in the `interceptData` struct

| Key       | Description                     |
| --------- | ------------------------------- |
| `token`   | The JWT token that was parsed   |
| `payload` | The JWT payload that was parsed |

## Example

{% code title="interceptors/SecurityAudit.cfc" %}

```javascript
component extends="coldbox.system.Interceptor"{

    function cbSecurity_onJWTCreation( event, interceptData ){
        // do what you like here
    }

}
```

{% endcode %}


# Introduction

Enterprise-grade security for ColdBox applications with authentication, authorization, JWT, CSRF protection, and comprehensive security headers.

<figure><img src="/files/Gp1E46w94KP79XchC4AO" alt="CBSecurity Logo"><figcaption><p>Enterprise Security for ColdBox Applications</p></figcaption></figure>

**CBSecurity** is a comprehensive security framework for ColdBox applications, providing enterprise-grade authentication, authorization, and protection mechanisms. It combines multiple security modules into a cohesive, easy-to-use security platform that helps developers build secure applications with minimal effort.

<figure><img src="/files/8P9XtI8UswO2u92zHG3B" alt="CBSecurity Visualizer Interface"><figcaption><p>Security Visualizer - Monitor and configure your security settings</p></figcaption></figure>

## 🎯 Core Security Capabilities

CBSecurity provides a multi-layered security approach with the following key capabilities:

### 🔐 Authentication & Authorization

* **Security Firewall** - Rule-based request protection using security rules engine and handler annotations
* **Authentication Manager** (`cbauth`) - Pluggable authentication system compatible with any authentication provider
* **Basic Authentication** - Built-in HTTP Basic Auth support with credential storage and browser challenge handling
* **Authorization Service** - Functional security API for authorization checks across all application layers

### 🎫 Token Management

* **JWT Services** (`jwtcfml`) - Complete JSON Web Token implementation with generation, decoding, and validation
* **Access & Refresh Tokens** - Native support for JWT-based authentication flows
* **Token Storage** - Flexible token storage with multiple backend options

### 🛡️ Security Protections

* **CSRF Protection** (`cbcsrf`) - Cross-Site Request Forgery protection for form submissions
* **Security Headers** - Industry-standard HTTP response headers (CSP, HSTS, X-Frame-Options, XSS Protection)
* **Password Generator** - Cryptographically secure random password generation

### 📊 Management & Monitoring

* **Security Visualizer** - Graphical interface for monitoring firewall activity and managing security configurations
* **Rule Engine** - Flexible security rules supporting XML, JSON, database, and model-based configurations
* **Module Integration** - Allows modules to contribute their own security rules and validation logic

## 🧩 Module Composition

CBSecurity is built on a modular architecture that integrates several specialized security modules:

![CBSecurity Architecture - Module integration with cbstorages for flexible storage](/files/-M8b8oOojXTh0tHlXruT)

The framework leverages `cbstorages` for flexible storage backends and seamlessly integrates with the ColdBox ecosystem to provide comprehensive security coverage across your entire application.

## ⭐ Key Features

### 📋 Flexible Security Rules

* **Multiple Storage Options** - Define rules in XML, JSON, databases, or ColdBox models
* **Regular Expression Support** - Use regex patterns or simple string matching for rule definitions
* **Modular Rules** - Modules can contribute their own security rules with custom validation logic
* **Dynamic Rule Loading** - Load and unload security rules at runtime from contributing modules

### 🔒 Advanced Authorization

* **Annotation-Driven Security** - Secure handlers and actions using ColdBox annotations
* **Cascading Security** - Hierarchical security rules from global to handler to action level
* **Functional API** - Injectable security service for authorization checks in any application layer
* **Custom Validators** - Each module can define its own security validator implementation

### 🔑 Authentication Flexibility

* **Multiple Authentication Providers** - Works with `cbauth`, ColdFusion native authentication, or custom providers
* **Provider Agnostic** - Implements standard interfaces allowing any authentication system integration
* **Basic Authentication** - Built-in HTTP Basic Auth with credential storage
* **JWT Token Management** - Complete support for JWT access and refresh token workflows

### ⚡ Security Response Handling

* **Granular Control** - Distinguish between authentication failures and authorization denials
* **Customizable Actions** - Configure different responses for invalid authentication vs. authorization
* **Event-Driven** - Hook into security events for custom logging, monitoring, or response handling

## 📜 License

CBSecurity is open-source software licensed under the [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0).

## 📚 Resources

### 📖 Documentation & Support

* **Documentation** - <https://coldbox-security.ortusbooks.com>
* **Source Code** - <https://github.com/coldbox-modules/cbsecurity>
* **Issue Tracker** - <https://github.com/coldbox-modules/cbsecurity/issues>
* **Community Forum** - [https://community.ortussolutions.com/c/box-modules/cbsecurity/](https://community.ortussolutions.com/c/box-modules/cbsecurity/26)

### 💬 Getting Help

The ColdBox community is active and ready to help:

* **Community Forum** - Ask questions and share knowledge with other developers
* **GitHub Issues** - Report bugs and request features
* **Professional Support** - Enterprise support available through Ortus Solutions

## 🏢 Professional Open Source

![Ortus Solutions, Corp](https://blobscdn.gitbook.com/v0/b/gitbook-28427.appspot.com/o/assets%2F-LA-UVvG0NM7NpDzssBL%2F-LA-Uaei0WzTH7Su5CR7%2F-LA-UqN1BRXynZ7RUVO7%2Fortussolutions_button.png?generation=1523647999385555\&alt=media)

CBSecurity is professionally developed and supported by [Ortus Solutions, Corp](http://www.ortussolutions.com/services), a leader in CFML consulting and development.

### 🚀 Enterprise Services

Ortus Solutions offers comprehensive professional services for CBSecurity and the ColdBox Platform:

* **🛠️ Custom Development** - Tailored security solutions for your specific requirements
* **👨‍🏫 Professional Support & Mentoring** - Expert guidance from the creators of ColdBox
* **📚 Training** - Official ColdBox and security training programs
* **🔍 Architecture & Code Reviews** - Expert evaluation of your security implementation
* **⚡ Performance Optimization** - Server tuning and application optimization
* **🔐 Security Hardening** - Comprehensive security audits and hardening services

[Learn more about our services](http://www.ortussolutions.com/services)

***

## 🙏 HONOR GOES TO GOD ABOVE ALL

Because of His grace, this project exists. If you don't like this, then don't read it; it's not for you.

> "Therefore being justified by **faith**, we have peace with God through our Lord Jesus Christ: By whom also we have access by **faith** into this **grace** wherein we stand, and rejoice in hope of the glory of God." Romans 5:5


# Release History

A brief history in time of our major releases

In this section you will find the release notes for each version we release under this major version.  If you are looking for the release notes of previous major versions use the version switcher at the top left of this documentation book.  Here is a breakdown of our major version releases.

## Version 3.0

Version 3 is a major rewrite of this module.  It drops Adobe 2016 support and enhances the way the firewall is configured.  It also add major capabilities for security headers, csrf settings and much more.

It also introduces the ability for the firewall to do 401 response blocks as actions for security rules.  The CBSecurity visualizer is also a major addition that allows a developer or manager to visualize the performance of the firewall and visualize all the configurations necessary for operation.

Finally, we have introduced basic authentication for your applications with an optional user credential in-memory storage.

## Version 2.0

Version 2 is a major release of our security module.  We completely refactored the engine to make it more modern and to adhere to our new coding standards.  We then proceeded to enhance it to tap into our HMVC approach and allow rules to be contributed from modules themselves. We also added annotation driven security to complete the ability to secure not only incoming requests by rules but also by easy annotations.

We have made great strides in this release to make it a one-stop-shop for security concerns within ColdBox applications.

## Version 1.0

Our first release as a module decoupled from the ColdBox 2 days!


# What's new With 3.7.0

January 14, 2026

#### Changed

* Increased VARCHAR field sizes in `DBLogger` table schema to accommodate longer URLs and user agent strings. Fields `host`, `path`, `queryString`, `referer`, and `userAgent` now use VARCHAR(1024) to prevent truncation of data.
* Updated `DBLogger` insert statements to truncate `host`, `path`, `queryString`, `referer`, and `userAgent` values to 1024 characters using `left()` function to prevent database errors.

#### Fixed

* Allow submodules to load after **cbsecurity** loads.
* Make sure the JWT token is not null when doing discovery in the JWT Service.
* Fixed `isSafeRedirectUrl()` host comparison for non-default ports by stripping port from host before comparing with URI host.
* ACF Compatibility: Fixed `dateTimeFormat` usage for `logDate` in activity view to prevent conversion errors in Adobe ColdFusion.

#### Added

* Added `TokenRejectionException` handling in the JWT handler to properly handle token rejection errors.
* Updated JWT handler error message calls to match the specification.
* Added test cases for non-default port scenarios in `isSafeRedirectUrl()` validation.
* Added test validation for JWT response messages.


# What's New With 3.6.0

2025-12-08

#### Security

* **CRITICAL**: Fixed open redirect vulnerability in `_securedURL` handling. The `saveSecuredUrl()` method now validates redirect URLs to ensure they belong to the same host as the current request, preventing attackers from crafting malicious URLs that redirect users to external sites after login. Added `isSafeRedirectUrl()` validation  `java.net.URI` to compare hosts.

#### Fixed

* BOX-164 Allow Visualizer to show settings when `firewall.logging` not enabled
* JWT Handler improperly returns a value, causing it to skip ColdBox's RestHandler's response formatting logic. This results in the entire response object being returned rather than just invoking getDataPacket()


# What's New With 3.5.0

What's new with CBSecurity 3.5.0

CBSecurity 3.5.0 is a significant modernization release that brings enhanced platform support, improved development workflows, and comprehensive AI assistance capabilities.

## BoxLang Certification

CBSecurity 3.5.0 has been fully certified for **BoxLang**, the modern dynamic JVM language. This includes:

* Complete compatibility testing with BoxLang runtime
* Validated functionality across all CBSecurity features
* Updated examples and documentation for BoxLang syntax
* Full test harness coverage for BoxLang environments

## ColdBox 8 Support

This release adds official support and certification for **ColdBox 8**, ensuring CBSecurity works seamlessly with the latest ColdBox framework features and improvements.

## Enhanced Development Workflows

### GitHub Actions Updates

The project has migrated to modern GitHub Actions workflows, providing:

* Improved CI/CD pipeline reliability
* Better cross-platform testing coverage
* Automated testing across multiple CFML engines
* Enhanced security scanning and dependency management

### Test Harness Improvements

The test harness has been significantly upgraded to provide:

* Better local development experience
* Enhanced integration testing capabilities
* Improved TestBox runner configuration
* Streamlined server startup and configuration

## AI-Powered Development Assistance

### GitHub Copilot Instructions

CBSecurity 3.5.0 introduces comprehensive AI assistance through:

* **`.github/copilot-instructions.md`** - Detailed guidance for AI agents covering:
  * Module architecture and component relationships
  * Security validator patterns and implementation
  * Interceptor flow and event handling
  * Development workflows and best practices
  * Test harness setup and TestBox runner details

This enhancement enables AI tools like GitHub Copilot to provide more accurate and contextual assistance when working with CBSecurity.

## Developer Experience Improvements

### Documentation Enhancements

* Documented test-harness structure and usage patterns
* Enhanced TestBox runner details for local integration testing
* Improved developer workflow documentation
* Better guidance for module extension and customization

### Local Development Setup

The release includes improved documentation and tooling for:

* Setting up local development environments
* Running integration tests via `test-harness/tests/runner.cfm`
* Using `box.json` scripts for common development tasks
* Server configuration for different CFML engines

## System Requirements

* **ColdBox Framework**: 6+ (ColdBox 8 certified)
* **CFML Engines**: BoxLang 1+ (Preferred), Lucee 5+, Adobe 2023+
* **CommandBox**: 5.0+

## Compatibility Notes

This release maintains full backward compatibility with existing CBSecurity 3.x installations. No breaking changes have been introduced.

## Migration Notes

No migration steps are required for this release. Simply update your CBSecurity module dependency:

```bash
# Update to latest version
box update cbsecurity

# Or install specific version
box install cbsecurity@3.5.0
```

## Related Resources

* [CBSecurity Documentation](https://coldbox-security.ortusbooks.com/)
* [Source Code](https://github.com/coldbox-modules/cbsecurity)
* [Issue Tracker](https://ortussolutions.atlassian.net/projects/BOX/issues)
* [BoxLang Documentation](https://boxlang.ortusbooks.com/)


# What's New With 3.4.3

What's new with CBSecurity 3.4.3

CBSecurity 3.4.3 is a maintenance release that addresses ColdBox 7 compatibility requirements.

## ColdBox 7 Compliance

### View Rendering Method Update

The primary change in this release addresses a breaking change in ColdBox 7:

* **Fixed**: Renamed `renderView()` to `view()` to be ColdBox 7 compliant
* This change ensures CBSecurity works properly with ColdBox 7's updated view rendering methods
* Maintains backward compatibility with earlier ColdBox versions

## System Requirements

* **ColdBox Framework**: 6+ (ColdBox 7 compliant)
* **CFML Engines**: Adobe ColdFusion 2018+, Lucee 5+
* **CommandBox**: 5.0+

## Compatibility Notes

This release maintains full backward compatibility with existing CBSecurity 3.x installations while ensuring forward compatibility with ColdBox 7.

## Migration Notes

No migration steps are required for this release. Simply update your CBSecurity module dependency:

```bash
# Update to latest version
box update cbsecurity

# Or install specific version
box install cbsecurity@3.4.3
```

## Related Resources

* [CBSecurity Documentation](https://coldbox-security.ortusbooks.com/)
* [Source Code](https://github.com/coldbox-modules/cbsecurity)
* [Issue Tracker](https://ortussolutions.atlassian.net/projects/BOX/issues)
* [ColdBox Framework](https://coldbox.ortusbooks.com/)


# What's New With 3.4.2

What's new with CBSecurity 3.4.2

CBSecurity 3.4.2 is a maintenance release that addresses database compatibility issues and improves documentation standards.

## Database Compatibility Improvements

### Oracle Database Support

* **Fixed**: Updated security logs columns to work with Oracle databases using `clob` data type
* This enhancement ensures CBSecurity's logging functionality works seamlessly with Oracle database environments
* Improves enterprise database compatibility for security audit trails

### Security Logs Configuration

* **Fixed**: `cbsecurity_logs` table name is now properly referenced instead of being hard-coded
* This change ensures the module setting for the logs table name is properly respected
* Provides better flexibility for custom table naming conventions

## Documentation Improvements

### Markdown Rules Updates

* **Fixed**: Updated markdown rules to eliminate duplicate headers
* Improved documentation consistency and readability
* Enhanced GitBook compatibility and navigation structure

## System Requirements

* **ColdBox Framework**: 6+
* **CFML Engines**: Adobe ColdFusion 2018+, Lucee 5+
* **CommandBox**: 5.0+
* **Database**: Any supported database (Oracle compatibility enhanced)

## Compatibility Notes

This release maintains full backward compatibility with existing CBSecurity 3.x installations while improving database compatibility across different database engines.

## Migration Notes

No migration steps are required for this release. Simply update your CBSecurity module dependency:

```bash
# Update to latest version
box update cbsecurity

# Or install specific version
box install cbsecurity@3.4.2
```

### Oracle Database Users

If you're using Oracle and experiencing issues with security logs, this update will resolve column type compatibility issues. No manual database changes are required.

## Related Resources

* [CBSecurity Documentation](https://coldbox-security.ortusbooks.com/)
* [Source Code](https://github.com/coldbox-modules/cbsecurity)
* [Issue Tracker](https://ortussolutions.atlassian.net/projects/BOX/issues)
* [Database Configuration Guide](/getting-started/configuration/firewall/untitled)


# What's New With 3.4.1

What's new with CBSecurity 3.4.1

CBSecurity 3.4.1 is a targeted maintenance release that addresses a specific database compatibility issue with Microsoft SQL Server.

## Database Compatibility Fix

### Microsoft SQL Server Support

* **Fixed**: Added proper parenthesis on `TOP` statements for Microsoft SQL Server in the `DBLogger`
* This fix resolves SQL syntax errors that were occurring when using CBSecurity's database logging features with MSSQL Server
* Thanks to @irvirv for identifying and helping resolve this issue

## System Requirements

* **ColdBox Framework**: 6+
* **CFML Engines**: Adobe ColdFusion 2018+, Lucee 5+
* **CommandBox**: 5.0+
* **Database**: Any supported database (MSSQL Server compatibility enhanced)

## Compatibility Notes

This release maintains full backward compatibility with existing CBSecurity 3.x installations while fixing a specific SQL syntax issue affecting Microsoft SQL Server users.

## Migration Notes

No migration steps are required for this release. Simply update your CBSecurity module dependency:

```bash
# Update to latest version
box update cbsecurity

# Or install specific version
box install cbsecurity@3.4.1
```

### Microsoft SQL Server Users

If you're using Microsoft SQL Server and experiencing SQL syntax errors in the DBLogger, this update will resolve those issues. No manual database changes are required.

## Related Resources

* [CBSecurity Documentation](https://coldbox-security.ortusbooks.com/)
* [Source Code](https://github.com/coldbox-modules/cbsecurity)
* [Issue Tracker](https://ortussolutions.atlassian.net/projects/BOX/issues)
* [Database Configuration Guide](/getting-started/configuration/firewall/untitled)


# What's New With 3.4.0

June 14, 2023

## Added

* Official Adobe 2023 Support
* Gitflows for testing all engines and all versions of ColdBox
* Added `transientCache=false` to auth `User` to avoid any issues when doing security operations
* Added population control for auth `User` for extra security

## Fixed

* `User` auth was not serializing the `id` of the user in the mementifier config


# What's New With 3.3.0

March 31, 2023

### Added

* Added `guest()` method to CBSecurity model and `Authorizable` delegate


# What's New With 3.2.0

March 29, 2023

### Added

* Migrations table for security logs
* New bootsrap icons + css + js
* New github support files

### Fixed

* `getActionsReport()` was not defaulting the type's structure, so exceptions would arise when there was no data in the visualizer


# What's New With 3.1.0

2023-FEB-17

### Added

* Added a new helper: `createPassword()` on the `CBSecurity` model to generate secure, random passwords with letters, symbols, and numbers.

{% content-ref url="/pages/eA8bHiGeEkS9nCF1E2sT" %}
[Utility Methods](/usage/cbsecurity-model/utility-methods)
{% endcontent-ref %}

* `cbcsrf` Upgraded to version 3, which we missed in the previous release.


# What's New With 3.0.0

January 2023

<figure><img src="/files/VGb2S36qNCuaXY6fihE6" alt=""><figcaption><p>v3.x Release</p></figcaption></figure>

### Compatibility

* Dropped Adobe ColdFusion 2016
* New **`JwtAuthValidator`** instead of mixing concerns with the `JwtService`. You will have to update your configuration to use this `validator` instead of the `JwtService`
* All settings have changed. They are not single-level anymore. They are now grouped by functionality. Please see the [Configuration](/getting-started/configuration) area for the new approach.

### Added

* New ability for the firewall to log all action events to a database table.
* If enabled, a new visualizer can visualize all settings and firewall events via the log table.
* New Basic Auth validator and basic auth user credentials storage system. This will allow you to secure apps where no database interaction is needed or required.
* New global and rule action: `block` and the firewall will block the request with a 401 Unauthorized page.
* New event `cbSecurity_onFirewallBlock` announced whenever the firewall blocks a request into the system with a 403.
* `DBTokenStorage` now rotates using the async scheduler and not direct usage anymore.
* Ability to set the `cbcsrf` module settings into the `cbsecurity` settings as `csrf`.
* We now default the user service class and the auth token rotation events according to the user authentication service (cbauth, etc.); no need to duplicate work.
* New rule-based IP security. You can add a `allowedIPs` key into any rule and add which IP Addresses are allowed into the match. By default, it matches all IPs.
* New rule-based HTTP method security. You can add a `httpMethods` key into any rule and add which HTTP methods are allowed into the match. By default, it matches all HTTP Verbs.
* New `securityHeaders` configuration to allow a developer to protect their apps from common exploits: XSS, HSTS, Content Type Options, host header validation, IP validation, clickjacking, non-SSL redirection, and much more.
* The security firewall now stores the authenticated user according to the `prcUserVariable` on authenticated calls via `preProcess()` no matter the validator used
* Dynamic Custom Claims: You can pass a function/closure as the value for a custom claim, and it will be evaluated at runtime, passing in the current claims before being encoded
* Allow passing in custom refresh token claims to `attempt()` and `fromUser()` and `refreshToken()` : `refreshCustomClaims`
* Added `TokenInvalidException` and `TokenExpiredException` to the `refreshToken` endpoint

### Fixed

* Disable lastAccessTimeouts for JWT CacheTokenStorage BOX-128
* Fix spelling of property `datasource` on `queryExecute` that was causing a read issue.


# Upgrade to 3.0.0

CBSecurity 3 is a major release and it will require some updates in order for you to fully upgrade your previous versions.

## Adobe 2016, 2018 Support Dropped

These engines are no longer supported

## JwtService Validator Deprecated

In the previous releases the validator for JWT was `JwtService@cbsecurity`. This has now changed to `JwtAuthValidator@cbsecurity`. So make sure you update your configurations.

## CBAuthValidator Deprecated

The `CBAuthValidator` has been renamed to just `AuthValidator`. This validator is now not `cbauth` focused but `IAuthService` focused. It also supports role and permission based authorization.

## Settings Structure

The entire settings structure has been redesigned to support many features in a a more concise and block approach. All top-level settings have been removed and added to specific sections. Please review the [Configuration](/getting-started/configuration) section in detail to see where the new settings belongs to.


# About This Book

A little more info about this book

The source code for this book is hosted on GitHub: <https://github.com/ortus-docs/cbsecurity-docs>. You can freely contribute to it and submit pull requests. The contents of this book are copyrighted by [Ortus Solutions, Corp](http://www.ortussolutions.com/) and cannot be altered or reproduced without the author's consent. All content is provided *"As-Is"* and can be freely distributed.

* The majority of code examples in this book are done in `cfscript`.
* The majority of code generation and running of examples are done via **CommandBox**: The ColdFusion (CFML) CLI, Package Manager, REPL - <https://www.ortussolutions.com/products/commandbox>​

## External Trademarks & Copyrights <a href="#external-trademarks-and-copyrights" id="external-trademarks-and-copyrights"></a>

Flash, Flex, ColdFusion, and Adobe are registered trademarks and copyrights of Adobe Systems, Inc.

## Notice of Liability <a href="#notice-of-liability" id="notice-of-liability"></a>

The information in this book is distributed “as is” without warranty. The author and Ortus Solutions, Corp shall not have any liability to any person or entity concerning loss or damage caused or alleged to be caused directly or indirectly by the content of this training book, software, and resources described in it.

## Contributing <a href="#contributing" id="contributing"></a>

We highly encourage contributions to this book and our open-source software. The source code for this book can be found in our [GitHub repository](https://github.com/ortus-docs/cbsecurity-docs), where you can submit pull requests.

## Charitable Proceeds <a href="#charitable-proceeds" id="charitable-proceeds"></a>

10% of the proceeds of this book will go to charity to support orphaned kids in El Salvador - <https://www.harvesting.org/>. So please donate and purchase the printed version of this book; every book sold can help a child for almost two months.

### Shalom Children's Home <a href="#shalom-childrens-home" id="shalom-childrens-home"></a>

**Shalom Children’s Home** is one of the ministries dear to our hearts in El Salvador. During the 12-year civil war that ended in 1990, many children were left orphaned or abandoned by parents who fled El Salvador. The Benners saw the need to help these children and received 13 children in 1982. Little by little, more children came on their own, churches and the government brought children to them for care, and the Shalom Children’s Home was founded.

Shalom now cares for over 80 children in El Salvador, from newborns to 18 years old. They receive shelter, clothing, food, medical care, education, and life skills training in a Christian environment. A child sponsorship program supports the home.

We have personally supported Shalom since; it is a place of blessing for many children in El Salvador who either have no families or have been abandoned. This is a good earth to seed and plant.


# Author

About our authors

## Luis Fernando Majano Lainez <a href="#luis-fernando-majano-lainez" id="luis-fernando-majano-lainez"></a>

![](/files/-Lp-0mh7rFCs1esEicGW)

Luis Majano is a Computer Engineer who has been developing and designing software systems since 2000. He was born in [San Salvador, El Salvador](http://en.wikipedia.org/wiki/El_Salvador) in the late 70s, during a period of economical instability and civil war. He lived in El Salvador until 1995 and then moved to Miami, Florida where he completed his Bachelor of Science in Computer Engineering at [Florida International University](http://fiu.edu).&#x20;

He is the CEO of [Ortus Solutions](http://www.ortussolutions.com), a consulting firm specializing in web development, ColdFusion (CFML), Java development, and all open-source professional services under the ColdBox and ContentBox stack. He is the creator of ColdBox, ContentBox, WireBox, CommandBox, LogBox, and anything “BOX” and contributes to many open-source ColdFusion/Java projects. You can read his blog at [www.luismajano.com](http://www.luismajano.com)

Luis is passionate about Jesus, tennis, golf, volleyball, and anything electronic. Random Author Facts:

* He played volleyball in the Salvadorean National Team at the tender age of 17
* The Lord of the Rings and The Hobbit are his favorite books(Geek!)
* His first ever computer was a Texas Instrument TI-86 that his parents gave him in 1986. After some time digesting his very first BASIC book, he had written his own tic-tac-toe game at the age of 9. (Extra geek!)
* He has a geek love for circuits, microcontrollers, and overall embedded systems.
* He has, of late (during old age), become a fan of organic gardening.

> Keep Jesus number one in your life and in your heart. I did and it changed my life from desolation, defeat and failure to an abundant life full of love, thankfulness, joy and overwhelming peace. As this world breathes failure and fear upon any life, Jesus brings power, love and a sound mind to everybody!
>
> “Trust in the LORD with all your heart, and do not lean on your own understanding.” \
> &#x20;Proverbs 3:5

## Contributors <a href="#contributors" id="contributors"></a>

### Will de Bruin <a href="#will-de-bruin" id="will-de-bruin"></a>

### Brad Wood <a href="#brad-wood" id="brad-wood"></a>


# Installation

Get up and running with CBSecurity in no time!

Leverage [CommandBox](https://www.ortussolutions.com/products/commandbox) to install into your ColdBox app:

```bash
# Latest version
install cbsecurity

# Bleeding Edge
install cbsecurity@be
```

## System Requirements

### CFML Engines

* BoxLang 1+ (Preferred)
* Lucee 5+
* Adobe 2023+

### Additional Requirements

* A database for optional firewall logging
* ColdBox 7+ for delegates and basic auth support only

## Mixins

The following mixins are registered once the module is installed:

```javascript
/**
 * Retrieve the Jwt Auth Service
 */
function jwtAuth()

/**
 * Retrieve the CBSecurity Service Object
 */
function cbSecure()
```

## Configuration Settings

By default `cbsecurity` is configured to work with `cbauth` as the authentication service. You only need to provide a user service class that knows how to connect to your database to retrieve and validate credentials. You can also use the in-built basic authentication users as well.

{% hint style="success" %}
You can find much more information about cbauth here: <https://forgebox.io/view/cbauth>
{% endhint %}

{% content-ref url="/pages/-LA-UqLbEQoweJk3ZTf5" %}
[Configuration](/getting-started/configuration)
{% endcontent-ref %}


# Overview

In this page you will find a thorough overview of the capabilities of the ColdBox Security module.

## Authentication/Authorization

For any security system, you need to know **who** is authenticated (authentication) and **what** (authorization) this user is allowed to do. `cbsecurity` is no different, so it provides an:

* **Authentication system** which performs the following functions:
  * Validates user credentials
  * Logs them in and out
  * Tracks their security in sessions or any custom storage
* **Authorization** system which:
  * Validates permissions or roles or both or none at all :smile:

![](/files/-MibRo_dQtNni4Hpsjq7)

## CBSecurity Security Firewall

With CBSecurity, you can **secure** all your incoming ColdBox events from execution through security rules or discrete annotations within your handler's code. You will also be able to leverage our `CBSecurity` service model to secure any code context anywhere, from execution blocks to views and much more.

![ColdBox Security Firewall](/files/-MibTkPJXqBEKXpSN5FW)

The module wraps itself around the `preProcess` interception point (The first execution of a ColdBox request) will try to validate if the request has been authenticated and authorized to execute. &#x20;

### Validators

<figure><img src="/files/N16E4C9isPP6hIWGkXUa" alt=""><figcaption><p>Security Validators Process Flow</p></figcaption></figure>

This is done via security rules and/or annotations on the requested handler actions and through a CBSecurity `Validator` which knows how to authenticate and authorize the request.  CBSecurity ships with many validators:

* **Auth Validator**: this is the default validator, which provides authentication and *permission-*&#x62;ased security through our `IAuthService` and `IAuthUser` interfaces.
* **CFML Security Validator:** ColdBox security has had this validator since version 1,  and it will talk to the ColdFusion engine's security methods (`cflogin,cflogout`). It provides authentication and *role-based* security.
* **Basic Auth Validator:** This validator secures your app via [basic authentication](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication) browser challenges to incoming requests. It can also work with the `BasicAuthUserService` and provide you a basic user credentials storage within your configuration file.&#x20;
* **JWT Validator**: If you want to use JSON Web Tokens, the JWT Validator provides authorization and authentication by validating incoming access/refresh tokens via headers for RESTFul API communications.
* **Custom Validator:** You can define your own authentication and authorization engines and plug them into the cbsecurity framework.

### How Does Validation Happen?

How does the interceptor know a user doesn't or does have access? Well, here is where you register a Validator CFC (`validator` setting) with the interceptor that implements two validation functions: `ruleValidator()` and `annotationValidator()` that will allow the module to know if the user is logged in and has the right authorizations to continue with the execution.

{% hint style="info" %}
You can find an interface for these methods in `cbsecurity.interfaces.ISecurityValidator`
{% endhint %}

The validator has two options to determine if the user will be allowed access:

* The `ruleValidator`() function will evaluate configured [security rules](/usage/untitled-1)
* The  `annotationValidator()` function will look at [security annotations](/usage/security-annotations) in your handler and handler actions.

You can use rules, annotations, or even both. Rules are much more flexible and can be visualized in our security visualizer.  Also, note that rules will be evaluated before annotations.

The validators' job is to tell back to the firewall if they are allowed access and if they don't, what type of validation they broke: **authentication** or **authorization**.  It can also determine if the firewall should block the request.

> `Authentication` is when a user is NOT logged in
>
> `Authorization` is when a user does not have the right permissions to access an event/handler or action.

{% hint style="info" %}
In some special cases, the validator can also challenge the user to log in like our `BasicAuthValidator` which sends a unique HTTP Header to prompt the user for credentials.
{% endhint %}

## Validation Process

Once the firewall has the results and the user is **NOT** allowed access, the following will occur:

* The request that was blocked will be logged via LogBox with the offending IP and extra metadata
* If firewall database logging is turned on, we will log the block in our database logs so the visualizer can represent them.
* The current requested URL will be flashed into ColdBox Flash as `_securedURL` so it can be used in relocations
* If using a rule, the rule will be stored in `prc` as `cbsecurity_matchedRule`
* The validator results will be stored in `prc` as `cbsecurity_validatorResults`
* If the type of invalidation is `authentication` the `cbSecurity_onInvalidAuthentication` interception will be announced
* If the type of invalidation is `authorization` the `cbSecurity_onInvalidAuthorization` interception will be announced
* If the type is `authentication` the default action (`defaultAuthenticationAction`) for that type will be executed (An override or a relocation or a firewall block).
* If the type is `authorization` the default action (`defaultAuthorizationAction`) for that type will be executed (An override or a relocation or a firewall block).

## Security Rules vs. Annotation Security

Here are the basics of a security rule which can be defined in JSON, XML, database or CFML.  Please note that only the following keys are mandatory:

* `securelist`

{% code title="Security Rule" %}

```javascript
firewall : {
  rules : [
    {
        // A list of white list events or Uri's patterns
        "whiteList": "",
        // A list of secured list events or Uri's patterns
        "secureList": "",
        // Are we matching a ColdBox event or the URL: event|url
        "match": "event",
        // Which authorization roles a user must have in order to access the secure list
        "roles": "admin",
        // Which authorization permsissions a user must have in order to access the secure list
        "permissions": "",
        // What happens if the user is not authenticated or authorized
        // redirect or override or block
        "action" : "redirect",
        // If rule breaks, and you have a redirect it will redirect here, else use the global setting
        "redirect"      : "",
        // If rule breaks, and you have an event, it will override it, else use the global setting
	"overrideEvent" : "",
	// Force SSL if using a redirect
        "useSSL": false,
        // Which http methods are allowed to execute the incoming event/url
        "httpMethods" : "*",
        // Which IP Addresses are allowed to execute the incoming event/url
        "allowedIPs" : "*"
    }
  ]
}
```

{% endcode %}

{% code title="Annotations" %}

```javascript
// Secure the entire handler
component secured{

	function index(event,rc,prc){}
	function list(event,rc,prc){}

}
// Same as this
component secured=true{
}

// Do NOT secure the handler
component secured=false{
}
// Same as this, no annotation!
component{

	function index(event,rc,prc) secured{
	}

	function list(event,rc,prc) secured="list"{

	}
	 
```

{% endcode %}

Your application can be secured with security rules or handler and method annotations. Before making your choice, you should take the following arguments into consideration:

* Annotations are directly visible in your code but are very static.&#x20;
* Annotations can protect events. Rules can protect events and incoming URLs.
* Rules allow you to change your actions (override, redirect, or block) and target each rule. With annotations, you can only use your configured default action and target.
* When stored in a file or database, rules can be edited by admins at runtime.

### Security Rules

Global Rules can be declared in your `config/ColdBox.cfc` in plain CFML or in any module's `ModuleConfig.cfc` or they can come from the following global sources:

* A JSON file
* An XML file
* The database by adding the configuration settings for it
* A model by executing a `getSecurityRules()` method from it or any method of your choice

#### Rule Anatomy

A rule is a struct that can be composed of the following elements. All of them are optional except the `secureList`.

```javascript
firewall : {
  rules : [
    {
        // A list of white list events or Uri's patterns
        "whiteList": "",
        // A list of secured list events or Uri's patterns
        "secureList": "",
        // Are we matching a ColdBox event or the URL: event|url
        "match": "event",
        // Which authorization roles a user must have in order to access the secure list
        "roles": "admin",
        // Which authorization permsissions a user must have in order to access the secure list
        "permissions": "",
        // What happens if the user is not authenticated or authorized
        // redirect or override or block
        "action" : "redirect",
        // If rule breaks, and you have a redirect it will redirect here, else use the global setting
        "redirect"      : "",
        // If rule breaks, and you have an event, it will override it, else use the global setting
	"overrideEvent" : "",
	// Force SSL if using a redirect
        "useSSL": false,
        // Which http methods are allowed to execute the incoming event/url
        "httpMethods" : "*",
        // Which IP Addresses are allowed to execute the incoming event/url
        "allowedIPs" : "*"
    }
  ]
}
```

#### Global Rules

Rules can be declared globally in your `config/ColdBox.cfc` or they can also be placed in any custom module in your application.  Here is the shorthand approach to defining rules:

{% code title="config/Coldbox.cfc" %}

```javascript
// CB Security
cbSecurity : {
    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"  : "security.login",
	// Default Auhtentication Action: override or redirect when a user has not logged in
	"defaultAuthenticationAction" : "redirect",
	// The global invalid authorization event or URI or URL to go if an invalid authorization occurs
	"invalidAuthorizationEvent"   : "security.notAuthorized",
	// Default Authorization Action: override or redirect when a user does not have enough permissions to access something
	"defaultAuthorizationAction"  : "redirect",
        // Firewall database event logs.
	"logs" : {
		"enabled"    : true,
		"table"      : "cbsecurity_logs",
		"autoCreate" : true
	},
	// The global security rules defined inline 
        "rules" : [
            {
                "securelist": "^admin",
                "match": "event",
                "roles": "admin",
                "action" : "redirect"
            },
            {
                "securelist": "^noAction",
                "match": "url",
                "roles": "admin"
            },
            {
                "securelist": "ruleActionOverride",
                "match": "url",
                "action" : "override",
                "overrideEvent": "main.login"
            },
            {
                "securelist": "override",
                "match": "url",
                "overrideEvent" : "security.login"
            },
            {
                "securelist": "ruleActionRedirect",
                "match": "url",
                "redirect": "main.login"
            }
        ]
    }
};
```

{% endcode %}

As you can see, you can combine all the security rule keys as you see fit.  Here is the same config, but the rules will come from a JSON file:

```javascript
// CB Security
cbSecurity : {
    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"  : "security.login",
	// Default Auhtentication Action: override or redirect when a user has not logged in
	"defaultAuthenticationAction" : "redirect",
	// The global invalid authorization event or URI or URL to go if an invalid authorization occurs
	"invalidAuthorizationEvent"   : "security.notAuthorized",
	// Default Authorization Action: override or redirect when a user does not have enough permissions to access something
	"defaultAuthorizationAction"  : "redirect",
        // Firewall database event logs.
	"logs" : {
		"enabled"    : true,
		"table"      : "cbsecurity_logs",
		"autoCreate" : true
	},
        "rules" : {
        	"useRegex" : true,
        	"defaults" :{ name : "" },
        	"provider" : {
        	  "source" : "config/security-rules.json.cfm"
        	}
        }
    }
};
```

### Annotation Security

The firewall will inspect handlers for the `secured` annotation. This annotation can be added to the entire handler or to an action, or both. The default value of the `secured` annotation is a Boolean `true`. This means we need a user to be authenticated in order to access it.

{% code title="handlers" %}

```javascript
// Secure this handler
component secured{

    function index(event,rc,prc){}
    function list(event,rc,prc){}

}

// Same as this
component secured=true{
}

// Not the same as this
component secured=false{
}
// Or this
component{

    function index(event,rc,prc) secured{

    }

    function list(event,rc,prc) secured="list"{

    }

}
```

{% endcode %}

#### Authorization Context

You can also give the annotation a value, which can be anything you like: A list of roles, a role, a list of permissions, metadata, etc. Whatever it is, this is the **authorization context,** and the user **validator** must be able to authenticate but authorize the context, or an invalid authorization will occur. **Ultimately it's up to the Validator to decide what that value does and means.**

{% code title="handler/users.cfc" %}

```javascript
// Secure this handler
component secured="admin,users"{

    function index(event,rc,prc) secured="list"{

    }

    function save(event,rc,prc) secured="write"{

    }

}
```

{% endcode %}

#### Cascading Security

By having the ability to annotate the **handler** and also the **action,** you create a cascading security model where they need to be able to access the handler first, and only then will the action be evaluated for access as well.

## Security Validators

As we mentioned at the beginning of this overview, the security module will use a **Validator** object to determine if the user has authentication/authorization or not. This setting is the `validator` setting and will point to the WireBox ID that implements the following methods: `ruleValidator() and annotationValidator().`  The validator can also be selected on a per module basis as well.

{% code title="ISecurityValidator" %}

```javascript
/**
 * Copyright since 2016 by Ortus Solutions, Corp
 * www.ortussolutions.com
 * ---
 * All security validators must implement the following methods
 */
interface{

	/**
	 * This function is called once an incoming event matches a security rule.
	 * You will receive the security rule that matched and an instance of the ColdBox controller.
	 *
	 * You must return a struct with three keys:
	 * - allow:boolean True, user can continue access, false, invalid access actions will ensue
	 * - type:string(authentication|authorization) The type of block that ocurred.  Either an authentication or an authorization issue
	 * - messages:string Info/debug messages
	 *
	 * @return { allow:boolean, type:string(authentication|authorization), messages:string }
	 */
	struct function ruleValidator( required rule, required controller );

	/**
	 * This function is called once access to a handler/action is detected.
	 * You will receive the secured annotation value and an instance of the ColdBox Controller
	 *
	 * You must return a struct with three keys:
	 * - allow:boolean True, user can continue access, false, invalid access actions will ensue
	 * - type:string(authentication|authorization) The type of block that ocurred.  Either an authentication or an authorization issue
	 * - messages:string Info/debug messages
	 *
	 * @return { allow:boolean, type:string(authentication|authorization), messages:string }
	 */
	struct function annotationValidator( required securedValue, required controller );

}

```

{% endcode %}

Each validator must return a `struct` with the following keys:

* `allow:boolean` A Boolean indicator if authentication or authorization was violated and we should block or not.  `True = allow, false = block`
* `type:stringOf(authentication|authorization)` A string that indicates the type of violation: authentication or authorization.
* `messages:string` Info or debugging messages

### AuthValidator

ColdBox security ships with the `AuthValidator@cbsecurity` which is the default validator in the configuration setting `validator`.  This validator can talk to ANY authentication service as long as it implements our `IAuthService` interface.  The typical methods it calls on your authentication service are:

* `isLoggedIn()`
* `getUser()`

It will then also talk to the User object returned from `getUser()` which must implement the `IAuthUser` interface.  The typical methods called on your User object are:

* `hasRole()`
* `hasPermission()`

These methods are used in order to determine authorizations.

```javascript
cbsecurity = {
    validator = "AuthValidator@cbsecurity"
}
```

{% hint style="success" %}
The `AuthValidator` will talk to the configured authentication service to validate authentication and authorization.
{% endhint %}

<pre class="language-javascript"><code class="lang-javascript">  cbAuth: {
    userServiceClass: "UserService"
<strong>  }
</strong></code></pre>

### BasicAuthValidator

This validator also ships with CBSecurity which will challenge users with browser-based basic authentication.  When used, it will use whatever authentication system and user service you have configured.  If you don't change the default settings, then CBSecurity will switch to using the `BasicAuthUserService` which allows you to store user credentials in your configuration file.  Let's see how to do that:

```javascript
cbsecurity = {
    firewall : {
        validator : "BasicAuthValidator@cbsecurity",
        invalidAuthenticationEvent : "security.invalid",
        invalidAuthorizationEvent : "security.notAuthorized",
        rules = [
            {
                secureList : "^admin"
            }
         ] 
    },
    basicAuth : {
        users : {
            "lmajano" : { password : "test" }
        }
    }
}
```

With this configuration, the basic auth validator will allow users to log in via the browser's basic authentication.  What about logging out then? Well, you have two options:

1. Close your browser, which clears the session
2. We ship with an endpoint to call for securely logging out: `/cbsecurity/basicauth/logout`

### Custom Validators

The second method of authentication is based on your custom security logic. You will be able to register a validation object with the module. Once a rule is matched, the module will call your validation object, send in the rule/annotation value and ask if the user can access it or not. It will be up to your logic to determine if the rule is satisfied or not. Below is a sample permission-based security validator:

{% code title="models/MySecurity.cfc" %}

```javascript
component singleton{

    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" };
        var user     = 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;
    }
}
```

{% endcode %}

## Authentication vs Authorization

The security module can distinguish between authentication issues and authorization issues. Once these actions are identified, the security module can act upon the result of these actions. These actions are based on the following 4 settings, but they all come down to three outcomes:

* Relocation to another event or URL
* An event override
* A firewall 401 Not Authorized block

<table data-header-hidden><thead><tr><th width="315.3333333333333">Setting</th><th width="119">Default</th><th>Description</th></tr></thead><tbody><tr><td>Setting</td><td>Default</td><td>Description</td></tr><tr><td><code>invalidAuthenticationEvent</code></td><td>---</td><td>The global invalid authentication event or URI or URL to go if an invalid authentication occurs</td></tr><tr><td><code>defaultAuthenticationAction</code></td><td><strong>redirect</strong></td><td>Default Authentication Action: override or redirect when a user has not logged in</td></tr><tr><td><code>invalidAuthorizationEvent</code></td><td>---</td><td>The global invalid authorization event or URI or URL to go if an invalid authorization occurs</td></tr><tr><td><code>defaultAuthorizationAction</code></td><td><strong>redirect</strong></td><td>Default Authorization Action: override or redirect when a user does not have enough permissions to access something</td></tr></tbody></table>

## Interceptions

### Authentication / Authorization

When invalid authentication or authorizations occur the interceptor will announce the following events:

* `cbSecurity_onInvalidAuthentication`
* `cbSecurity_onInvalidAuthorization`

You will receive the following data in the `interceptData` struct:

* `ip` : The offending IP address
* `rule` : The security rule intercepted or empty if annotations
* `settings` : The firewall settings
* `validatorResults` : The validator results
* `annotationType` : The annotation type intercepted, `handler` or `action` or empty if rule driven
* `processActions` : A Boolean indicator that defaults to **true**. If you change this to **false**, then the interceptor won't fire the invalid actions. Usually, this means, you manually will do them.

### Firewall Blocks

* `cbSecurity_onFirewallBlock` - When the firewall blocks an incoming request with a 403

You will receive the following data in the `interceptData` struct:

* `type` : The type of block: `hostheader` or `ipvalidation`
* `config` : The configuration structure of the rule
* `incomingIP` : The incoming ip if the type is `ipValiation`
* `incomingHost` : The incoming host if the type is `hostHeader`

## CBSecurity Model

The `CBSecurity` model was introduced in version 2.3.0, and it provides you with a way to provide authorization checks, utility security methods, and security contexts anywhere you like: handlers, layouts, views, interceptors, and even models.

Getting access to the model is easy via our `cbSecure()` mixin (handlers/layouts/views/interceptors) or injecting it via WireBox:

```javascript
// Mixin approach
cbSecure()

// Injection
property name="cbSecurity" inject="@CBSecurity";
```

Once injected, you can leverage it using our extraordinary methods listed below:

### **Blocking Methods**

When certain permission context is met, if not, throws `NotAuthorized`

* `secure( permissions, [message] )`
* `secureAll( permissions, [message] )`
* `secureNone( permissions, [message] )`
* `secureWhen( context, [message] )`

```javascript
// Only allow access to user_admin
cbSecure().secure( "USER_ADMIN" );

// Only allow access if you have all of these permissions
cbSecure().secureAll( "EDITOR, POST_PUBLISH" )

// YOu must not have this permission, if you do, kick you out
cbSecure().secureNone( "FORGEBOX_USER" )

// Secure using security evaluations
// Kick out if you do not have the AUTHOR_ADMIN or you are not the same incoming author
cbSecurity.secureWhen( 
    cbSecurity.none( "AUTHOR_ADMIN" ) && 
    !cbSecurity.sameUser( oAuthor )  
)

// Secure using a closure 
cbSecurity.secureWhen( ( user ) => !user.isConfirmed() );
```

### **Action Context Methods**

When a certain permission context is met, execute the success function/closure, else if a `fail` closure is defined, execute that instead.

* `when( permissions, success, fail )`
* `whenAll( permissions, success, fail )`
* `whenNone( permissions, success, fail )`

```javascript
var oAuthor = authorService.getOrFail( rc.authorId );
prc.data = userService.getData();

// Run Security Contexts
cbSecure()
    // Only user admin can change to the incoming role
    .when( "USER_ADMIN", ( user ) => oAuthor.setRole( roleService.get( rc.roleID ) ) )
    // The system admin can set a super admin
    .when( "SYSTEM_ADMIN", ( user ) => oAuthor.setRole( roleService.getSystemAdmin() ) )
    // Filter the data to be shown to the user
    .when( "USER_READ_ONLY", ( user ) => prc.data.filter( ( i ) => !i.isClassified ) )

// Calling with a fail closure
cbSecurity.when(
    "USER_ADMIN",
    ( user ) => user.setRole( "admin" ), //success
    ( user ) => relocate( "Invaliduser" ) //fail
);
```

### **Verification Methods**

Verify permissions or user equality

* `has( permissions ):boolean`
* `all( permissions ):boolean`
* `none( permissions ):boolean`
* `sameUser( user ):boolean`

```javascript
function edit( event, rc, prc ){
    var oUser = userService.getOrFail( rc.id ?: "" );
    if( !sameUser( oUser ) ){
        relocate( "/users" );
    }
}

<cfif cbsecure().all( "USER_ADMIN,USER_EDITOR" )>
    This is only visible to user admins!
</cfif>

<cfif cbsecure().has( "SYSTEM_ADMIN" )>
    <a href="/user/impersonate/#prc.user.getId()#">Impersonate User</a>
</cfif>

<cfif cbsecure().sameUser( prc.user )>
    <i class="fa fa-star">This is You!</i>
</cfif>
```

### **Request Context Methods**

* `secureView( permissions, successView, failView )`

{% code title="handlers/users.cfc" %}

```javascript
component{

    function index( event, rc, prc ){
     event.secureView( "USER_ADMIN", "users/admin/index", "users/index" ); 
    }

}
```

{% endcode %}

### Authentication Methods

You can leverage the model to do the following authentication-related methods:

* `authenticate( username, password )` : Authenticate a user
* `getAuthService()` : Get the configured auth service
* `getUserService()` : Get the configured user service
* `getUser()` : Get the authenticated user
* `isLoggedIn()` : Verify if a request is logged in
* `logout()` : Logout via the configured auth service

### Utility Methods

You can use the following methods to assist in your programming needs:

* `createPassword( length:32, letters:true, numbers:true, symbols:true )` : Generate a random and secure password
* `getRealIP( trustUpstream : true )` : Get a request's actual IP address
* `getRealHost( trustUpstream : true )` : Get a request's actual hostname used

## Security Visualizer

<figure><img src="/files/7YawV6uFq3auS4ygBOxU" alt=""><figcaption></figcaption></figure>

This module also ships with a security visualizer that will provide you with the following features:

* Visual representation of all settings
* Firewall reports
* Firewall activity logs
* Firewall rule simulator
* Much more&#x20;

You can access it via the `/cbsecurity` endpoint.

<figure><img src="/files/7VWPWzEBpYjUl04gpMkq" alt=""><figcaption><p>Rule Simulator</p></figcaption></figure>

Here are the quick visualizer configurations:

```
cbsecurity:{
    
    /**
    * --------------------------------------------------------------------------
    * Security Visualizer
    * --------------------------------------------------------------------------
    * This is a debugging panel that when active, a developer can visualize security settings and more.
    * You can use the `securityRule` to define what rule you want to use to secure the visualizer but make sure the `secured` flag is turned to true.
    * You don't have to specify the `secureList` key, we will do that for you.
    */
   visualizer : {
   	"enabled"      : true,
   	"secured"      : false,
   	"securityRule" : {}
   },

}
```

You can also secure it by adding `secured = true` which will create a new rule in the firewall where authentication is required in order to access the `/cbsecurity` endpoint. You can also modify the security rule by leveraging the `securityRule` key with whatever key options you would like to add.

{% hint style="danger" %}
**Important** The visualizer is disabled by default.  You have to manually enable it and secure it.
{% endhint %}

## JSON Web Tokens (JWT) REST Security

ColdBox Security offers a comprehensive feature set for RESTFul applications that require JSON web tokens.  We offer both access and refresh token capabilities.  Check out our [JWT Section](/jwt/jwt-services) for an in-depth overview.


# Configuration

How to configure CBSecurity

## Security Settings

By default, the security module will register itself for you using the module configuration settings you define in the`config/ColdBox.cfc.` You can create a `cbsecurity` key in the `modulesettings` or if you are in ColdBox 7 you can create a `config/modules/cbsecurity.cfc` as well.

Here you can see how to configure CBSecurity, but you can also navigate to the different configuration sections for an in-depth overview of those settings:

{% content-ref url="/pages/uRi79g32YNaf8uFamSIv" %}
[Authentication](/getting-started/configuration/authentication)
{% endcontent-ref %}

{% content-ref url="/pages/6zKMDTMV0PgYJaxtLX9x" %}
[Basic Auth](/getting-started/configuration/basic-auth)
{% endcontent-ref %}

{% content-ref url="/pages/lOScaFkxpmmMuTihVyFh" %}
[CSRF](/getting-started/configuration/csrf)
{% endcontent-ref %}

{% content-ref url="/pages/wyA59tn5FjyvtiJH16Pu" %}
[JWT](/getting-started/configuration/jwt)
{% endcontent-ref %}

{% content-ref url="/pages/8MzkrtobLucrZv5Eqy98" %}
[Firewall](/getting-started/configuration/firewall)
{% endcontent-ref %}

{% content-ref url="/pages/jvNuCcPokvuhrlDKGbRP" %}
[Security Headers](/getting-started/configuration/security-headers)
{% endcontent-ref %}

{% content-ref url="/pages/x10z0QwX3SYtnsle7U8O" %}
[Visualizer](/getting-started/configuration/visualizer)
{% endcontent-ref %}

### ColdBox Config

<pre class="language-javascript" data-title="config/Coldbox.cfc" data-line-numbers><code class="lang-javascript">// Module Settings
moduleSettings = {
    cbauth = {
	// This is the path to your user object that contains the credential validation methods
	userServiceClass = ""
    },

    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"                   : "CBAuthValidator@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"  : "",
		// Default Auhtentication Action: override or redirect when a user has not logged in
		"defaultAuthenticationAction" : "redirect",
		// The global invalid authorization event or URI or URL to go if an invalid authorization occurs
		"invalidAuthorizationEvent"   : "",
		// Default Authorization Action: override or redirect when a user does not have enough permissions to access something
		"defaultAuthorizationAction"  : "redirect",
		// Firewall database event logs.
		"logs" : {
			"enabled"    : false,
			"dsn"        : "",
			"schema"     : "",
			"table"      : "cbsecurity_logs",
			"autoCreate" : true
		},
		// Firewall Rules, this can be a struct of detailed configuration
		// or a simple array of inline rules
		"rules"                       : {
			// Use regular expression matching on the rule match types
			"useRegex" : true,
			// Force SSL for all relocations
			"useSSL"   : false,
			// A collection of default name-value pairs to add to ALL rules
			// This way you can add global roles, permissions, redirects, etc
			"defaults" : {},
			// You can store all your rules in this inline array
			"inline"   : [],
			// If you don't store the rules inline, then you can use a provider to load the rules
			// The source can be a json file, an xml file, model, db
			// Each provider can have it's appropriate properties as well. Please see the documentation for each provider.
			"provider" : { "source" : "", "properties" : {} }
		}
	},

	/**
	 * --------------------------------------------------------------------------
	 * Security Visualizer
	 * --------------------------------------------------------------------------
	 * This is a debugging panel that when active, a developer can visualize security settings and more.
	 * You can use the `securityRule` to define what rule you want to use to secure the visualizer but make sure the `secured` flag is turned to true.
	 * You don't have to specify the `secureList` key, we will do that for you.
	 */
	visualizer : {
		"enabled"      : false,
		"secured"      : false,
		"securityRule" : {}
	},

	/**
	 * --------------------------------------------------------------------------
	 * Security Headers
	 * --------------------------------------------------------------------------
	 * This section is the way to configure cbsecurity for header detection, inspection and setting for common
	 * security exploits like XSS, ClickJacking, Host Spoofing, IP Spoofing, Non SSL usage, HSTS and much more.
	 */
	securityHeaders                     : {
		// Master switch for security headers
		"enabled" : true,
		// If you trust the upstream then we will check the upstream first for specific headers
		"trustUpstream"         : false,
		// Content Security Policy
		// Content Security Policy (CSP) is an added layer of security that helps to detect and mitigate certain types of attacks,
		// including Cross-Site Scripting (XSS) and data injection attacks. These attacks are used for everything from data theft, to
		// site defacement, to malware distribution.
		// https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
		"contentSecurityPolicy" : {
			// Disabled by defautl as it is totally customizable
			"enabled" : false,
			// The custom policy to use, by default we don't include any
			"policy"  : ""
		},
		// The X-Content-Type-Options response HTTP header is a marker used by the server to indicate that the MIME types advertised in
		// the Content-Type headers should be followed and not be changed => X-Content-Type-Options: nosniff
		// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options
		"contentTypeOptions" : { "enabled" : true },
		"customHeaders"      : {
			// Name : value pairs as you see fit.
		},
		// Disable Click jacking: X-Frame-Options: DENY OR SAMEORIGIN
		// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
		"frameOptions" : { "enabled" : true, "value" : "SAMEORIGIN" },
		// HTTP Strict Transport Security (HSTS)
		// The HTTP Strict-Transport-Security response header (often abbreviated as HSTS)
		// informs browsers that the site should only be accessed using HTTPS, and that any future attempts to access it
		// using HTTP should automatically be converted to HTTPS.
		// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security,
		"hsts"         : {
			"enabled"           : true,
			// The time, in seconds, that the browser should remember that a site is only to be accessed using HTTPS, 1 year is the default
			"max-age"           : "31536000",
			// See Preloading Strict Transport Security for details. Not part of the specification.
			"preload"           : false,
			// If this optional parameter is specified, this rule applies to all of the site's subdomains as well.
			"includeSubDomains" : false
		},
		// Validates the host or x-forwarded-host to an allowed list of valid hosts
		"hostHeaderValidation" : {
			"enabled"      : false,
			// Allowed hosts list
			"allowedHosts" : ""
		},
		// Validates the ip address of the incoming request
		"ipValidation" : {
			"enabled"    : false,
			// Allowed IP list
			"allowedIPs" : ""
		},
		// The Referrer-Policy HTTP header controls how much referrer information (sent with the Referer header) should be included with requests.
		// Aside from the HTTP header, you can set this policy in HTML.
		// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy
		"referrerPolicy"     : { "enabled" : true, "policy" : "same-origin" },
		// Detect if the incoming requests are NON-SSL and if enabled, redirect with SSL
		"secureSSLRedirects" : { "enabled" : false },
		// Some browsers have built in support for filtering out reflected XSS attacks. Not foolproof, but it assists in XSS protection.
		// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection,
		// X-XSS-Protection: 1; mode=block
		"xssProtection"      : { "enabled" : true, "mode" : "block" }
	},

	/**
	 * --------------------------------------------------------------------------
	 * Json Web Tokens Settings
	 * --------------------------------------------------------------------------
	 * Here you can configure the JWT services for operation and storage.  In order for your firewall
	 * to leverage JWT authentication/authorization you must make sure you use the `JwtAuthValidator` as your
	 * validator of choice; either globally or at the module level.
	 */
	jwt                          : {
		// The issuer authority for the tokens, placed in the `iss` claim
		"issuer"                  : "",
		// The jwt secret encoding key, defaults to getSystemEnv( "JWT_SECRET", "" )
		"secretKey"               : getSystemSetting( "JWT_SECRET", "" ),
		// by default it uses the authorization bearer header, but you can also pass a custom one as well.
		"customAuthHeader"        : "x-auth-token",
		// The expiration in minutes for the jwt tokens
		"expiration"              : 60,
		// If true, enables refresh tokens, longer lived tokens (not implemented yet)
		"enableRefreshTokens"     : false,
		// The default expiration for refresh tokens, defaults to 30 days
		"refreshExpiration"          : 10080,
		// The Custom header to inspect for refresh tokens
		"customRefreshHeader"        : "x-refresh-token",
		// If enabled, the JWT validator will inspect the request for refresh tokens and expired access tokens
		// It will then automatically refresh them for you and return them back as
		// response headers in the same request according to the customRefreshHeader and customAuthHeader
		"enableAutoRefreshValidator" : false,
		// Enable the POST > /cbsecurity/refreshtoken API endpoint
		"enableRefreshEndpoint"      : true,
		// encryption algorithm to use, valid algorithms are: HS256, HS384, and HS512
		"algorithm"               : "HS512",
		// Which claims neds to be present on the jwt token or `TokenInvalidException` upon verification and decoding
		"requiredClaims"          : [] ,
		// The token storage settings
		"tokenStorage"            : {
			// enable or not, default is true
			"enabled"       : true,
			// A cache key prefix to use when storing the tokens
			"keyPrefix"     : "cbjwt_",
			// The driver to use: db, cachebox or a WireBox ID
			"driver"        : "cachebox",
			// Driver specific properties
			"properties"    : {
				"cacheName" : "default"
			}
		}
	}
<strong>};
</strong></code></pre>

### ColdBox 7 Config

In ColdBox 7 you can segregate module configurations so they are more manageable and have their own identity. Just create a `config/modules/cbsecurity.cfc` with a nice `configure()` method:

{% code title="config/cmo" lineNumbers="true" %}

```javascript
component{
    
    function configure(){
        return {
	/**
	 * --------------------------------------------------------------------------
	 * 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"                   : "CBAuthValidator@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"  : "",
		// Default Auhtentication Action: override or redirect when a user has not logged in
		"defaultAuthenticationAction" : "redirect",
		// The global invalid authorization event or URI or URL to go if an invalid authorization occurs
		"invalidAuthorizationEvent"   : "",
		// Default Authorization Action: override or redirect when a user does not have enough permissions to access something
		"defaultAuthorizationAction"  : "redirect",
		// Firewall database event logs.
		"logs" : {
			"enabled"    : false,
			"dsn"        : "",
			"schema"     : "",
			"table"      : "cbsecurity_logs",
			"autoCreate" : true
		},
		// Firewall Rules, this can be a struct of detailed configuration
		// or a simple array of inline rules
		"rules"                       : {
			// Use regular expression matching on the rule match types
			"useRegex" : true,
			// Force SSL for all relocations
			"useSSL"   : false,
			// A collection of default name-value pairs to add to ALL rules
			// This way you can add global roles, permissions, redirects, etc
			"defaults" : {},
			// You can store all your rules in this inline array
			"inline"   : [],
			// If you don't store the rules inline, then you can use a provider to load the rules
			// The source can be a json file, an xml file, model, db
			// Each provider can have it's appropriate properties as well. Please see the documentation for each provider.
			"provider" : { "source" : "", "properties" : {} }
		}
	},

	/**
	 * --------------------------------------------------------------------------
	 * Security Visualizer
	 * --------------------------------------------------------------------------
	 * This is a debugging panel that when active, a developer can visualize security settings and more.
	 * You can use the `securityRule` to define what rule you want to use to secure the visualizer but make sure the `secured` flag is turned to true.
	 * You don't have to specify the `secureList` key, we will do that for you.
	 */
	visualizer : {
		"enabled"      : false,
		"secured"      : false,
		"securityRule" : {}
	},

	/**
	 * --------------------------------------------------------------------------
	 * Security Headers
	 * --------------------------------------------------------------------------
	 * This section is the way to configure cbsecurity for header detection, inspection and setting for common
	 * security exploits like XSS, ClickJacking, Host Spoofing, IP Spoofing, Non SSL usage, HSTS and much more.
	 */
	securityHeaders                     : {
		// Master switch for security headers
		"enabled" : true,
		// If you trust the upstream then we will check the upstream first for specific headers
		"trustUpstream"         : false,
		// Content Security Policy
		// Content Security Policy (CSP) is an added layer of security that helps to detect and mitigate certain types of attacks,
		// including Cross-Site Scripting (XSS) and data injection attacks. These attacks are used for everything from data theft, to
		// site defacement, to malware distribution.
		// https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
		"contentSecurityPolicy" : {
			// Disabled by defautl as it is totally customizable
			"enabled" : false,
			// The custom policy to use, by default we don't include any
			"policy"  : ""
		},
		// The X-Content-Type-Options response HTTP header is a marker used by the server to indicate that the MIME types advertised in
		// the Content-Type headers should be followed and not be changed => X-Content-Type-Options: nosniff
		// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options
		"contentTypeOptions" : { "enabled" : true },
		"customHeaders"      : {
			// Name : value pairs as you see fit.
		},
		// Disable Click jacking: X-Frame-Options: DENY OR SAMEORIGIN
		// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
		"frameOptions" : { "enabled" : true, "value" : "SAMEORIGIN" },
		// HTTP Strict Transport Security (HSTS)
		// The HTTP Strict-Transport-Security response header (often abbreviated as HSTS)
		// informs browsers that the site should only be accessed using HTTPS, and that any future attempts to access it
		// using HTTP should automatically be converted to HTTPS.
		// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security,
		"hsts"         : {
			"enabled"           : true,
			// The time, in seconds, that the browser should remember that a site is only to be accessed using HTTPS, 1 year is the default
			"max-age"           : "31536000",
			// See Preloading Strict Transport Security for details. Not part of the specification.
			"preload"           : false,
			// If this optional parameter is specified, this rule applies to all of the site's subdomains as well.
			"includeSubDomains" : false
		},
		// Validates the host or x-forwarded-host to an allowed list of valid hosts
		"hostHeaderValidation" : {
			"enabled"      : false,
			// Allowed hosts list
			"allowedHosts" : ""
		},
		// Validates the ip address of the incoming request
		"ipValidation" : {
			"enabled"    : false,
			// Allowed IP list
			"allowedIPs" : ""
		},
		// The Referrer-Policy HTTP header controls how much referrer information (sent with the Referer header) should be included with requests.
		// Aside from the HTTP header, you can set this policy in HTML.
		// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy
		"referrerPolicy"     : { "enabled" : true, "policy" : "same-origin" },
		// Detect if the incoming requests are NON-SSL and if enabled, redirect with SSL
		"secureSSLRedirects" : { "enabled" : false },
		// Some browsers have built in support for filtering out reflected XSS attacks. Not foolproof, but it assists in XSS protection.
		// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection,
		// X-XSS-Protection: 1; mode=block
		"xssProtection"      : { "enabled" : true, "mode" : "block" }
	},

	/**
	 * --------------------------------------------------------------------------
	 * Json Web Tokens Settings
	 * --------------------------------------------------------------------------
	 * Here you can configure the JWT services for operation and storage.  In order for your firewall
	 * to leverage JWT authentication/authorization you must make sure you use the `JwtAuthValidator` as your
	 * validator of choice; either globally or at the module level.
	 */
	jwt                          : {
		// The issuer authority for the tokens, placed in the `iss` claim
		"issuer"                  : "",
		// The jwt secret encoding key, defaults to getSystemEnv( "JWT_SECRET", "" )
		"secretKey"               : getSystemSetting( "JWT_SECRET", "" ),
		// by default it uses the authorization bearer header, but you can also pass a custom one as well.
		"customAuthHeader"        : "x-auth-token",
		// The expiration in minutes for the jwt tokens
		"expiration"              : 60,
		// If true, enables refresh tokens, longer lived tokens (not implemented yet)
		"enableRefreshTokens"     : false,
		// The default expiration for refresh tokens, defaults to 30 days
		"refreshExpiration"          : 10080,
		// The Custom header to inspect for refresh tokens
		"customRefreshHeader"        : "x-refresh-token",
		// If enabled, the JWT validator will inspect the request for refresh tokens and expired access tokens
		// It will then automatically refresh them for you and return them back as
		// response headers in the same request according to the customRefreshHeader and customAuthHeader
		"enableAutoRefreshValidator" : false,
		// Enable the POST > /cbsecurity/refreshtoken API endpoint
		"enableRefreshEndpoint"      : true,
		// encryption algorithm to use, valid algorithms are: HS256, HS384, and HS512
		"algorithm"               : "HS512",
		// Which claims neds to be present on the jwt token or `TokenInvalidException` upon verification and decoding
		"requiredClaims"          : [] ,
		// The token storage settings
		"tokenStorage"            : {
			// enable or not, default is true
			"enabled"       : true,
			// A cache key prefix to use when storing the tokens
			"keyPrefix"     : "cbjwt_",
			// The driver to use: db, cachebox or a WireBox ID
			"driver"        : "cachebox",
			// Driver specific properties
			"properties"    : {
				"cacheName" : "default"
			}
		}
	};
    }
}
```

{% endcode %}

### Module Settings

Each module can also have its own CBSecurity settings which override or collaborate with the global settings. So what can a module do:

* Have its own validator
* Have its own security rules
* Have its own invalid authentication event and action
* Have its own invalid authorization event and action

You will create a `cbsecurity` struct within the module's `settings` struct in the `ModuleConfig.cfc`

{% code title="module/ModuleConfig.cfc" %}

```javascript
settings = {
    // CB Security Module Settings
    cbsecurity : {
      firewall : {
        // Module Relocation when an invalid access is detected, instead of each rule declaring one.
        "invalidAuthenticationEvent"  : "api:Home.onInvalidAuth",
        // Default Auhtentication Action: override or redirect 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"   : "api:Home.onInvalidAuthorization",
        // Default invalid action: override or redirect when an invalid access is detected, default is to redirect
        "defaultAuthorizationAction"  : "override",
        // The validator to use for this module
        "validator"                   : "JWTService@cbsecurity",
        // Inline rules
        "rules"                       : [ { "secureList" : "api:Secure\.*" } ]
        // Full rules
        // or a simple array of inline rules
	"rules"                       : {
	    // Use regular expression matching on the rule match types
	    "useRegex" : true,
	    // Force SSL for all relocations
	    "useSSL"   : false,
	    // A collection of default name-value pairs to add to ALL rules
	    // This way you can add global roles, permissions, redirects, etc
	    "defaults" : {},
	    // You can store all your rules in this inline array
	    "inline"   : [],
	    // If you don't store the rules inline, then you can use a provider to load the rules
	    // The source can be a json file, an xml file, model, db
	    // Each provider can have it's appropriate properties as well. Please see the documentation for each provider.
	    "provider" : { "source" : "", "properties" : {} }
	}
      }
    }
}
```

{% endcode %}

{% hint style="danger" %}
Please note that a module's security rules will be **PREPENDED** to the global rules
{% endhint %}

#### Loading/Unloading

Also note that if modules are loaded dynamically, it will still inspect them and register them if cbsecurity settings are found. The same goes for unloading, the entire security rules for that module will cease to exist.


# Authentication

Configuring your authentication services

You will configure the authentication and user services in the `authentication` area of CBSecurity.  CBSecurity ships with the [cbauth](https://github.com/elpete/cbauth) module that can provide you with a robust authentication service, session/request storage, interceptions, and much more. However, you can use any security authentication service as long as it matches our interface: `cbsecurity.interfaces.ISecurityValidator`.

{% content-ref url="/pages/-LpYn9wv0GkrraroFc2F" %}
[Authentication Services](/usage/authentication-services)
{% endcontent-ref %}

{% hint style="warning" %}
If you are using cbauth as your `authenticationService` (the default), you also need to [configure cbauth.](https://cbauth.ortusbooks.com/installation-and-usage)

```javascript
cbauth = {
    // This is the path to your user object that contains the credential 
    // validation methods
    userServiceClass = "models.UserService"
},
```

{% endhint %}

```javascript
/**
 * --------------------------------------------------------------------------
 * 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"     : cbauth.userServiceclass,
	// The name of the variable to use to store an authenticated user in prc scope on all incoming authenticated requests
	"prcUserVariable" : "oCurrentUser"
},
```

### Provider

The `provider` key is the WireBox ID of the authentication service that must adhere to our interface.

```javascript
"provider" : "SecurityService@contentbox"
```

### UserService

This key is not mandatory and will be automatically filled out from the `cbauth` user service class by default.  This class is used for CBSecurity to know how to retrieve users and validate credentials from whatever storage system you use.  This value can be a WireBox ID, and the object must adhere to our interface: `cbsecurity.interfaces.IUserService`.

```javascript
"provider" : "BasicAuthUserService@cbsecurity"
```

### prcUserVariable

This is a convenience setting that tells CBSecurity into which `prc` (private request context) variable to store the authenticated user on EVERY request.  This allows your entire codebase to talk to a single variable for the authenticated user.

```javascript
"prcUserVariable" : "oCurrentUser"
```


# Basic Auth

Configuration for basic authentication

The `basicAuth` key is used to store user credentials that will be used with [Basic Authentication](/usage/basic-authentication) and how the passwords are stored in memory.

```javascript
/**
 * --------------------------------------------------------------------------
 * 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          : {}
}
```

### HashAlgorithm

This is the default algorithm used when hashing the user storage passwords in memory.  The default is `SHA-512`

```javascript
hashAlgorithm  : "SHA-256",
```

### HashIterations

Iterates the number of times the hash is computed to create a more computationally intensive hash.  The default is `5`

```javascript
hashIterations  : 10,
```

### Users

This is the in-memory user storage system.  It's a `struct` and each **key** represents a unique `username` in the storage system.  Each user can then have the following attributes, but in reality, you can add as many attributes as you want.

* `password` - The only mandatory attribute.
* `firstName`
* `lastName`
* `roles`
* `permissions`

```javascript
users : {
    "lmajano" : { password : "test", permissions : "read,write",
    "guest" : { password : "guest", permissions : "read" }
}
```


# CSRF

Configuring CBSecurity for cross site request forgery attacks

CBSecurity ships with the `cbsrf` module and can be configured in line with the `cbsecurity` key.

{% hint style="warning" %}
Please note that if any update is made to that module, verify its settings in the module's configuration documentation: <https://forgebox.io/view/cbcsrf>
{% endhint %}

```
/**
 * --------------------------------------------------------------------------
 * 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
},
```

### EnableAutoVerifier

By default, this setting is turned off.  If you turn it on, then every non-GET request will be verified that it contains a valid incoming csrf token via a header or the incoming rc.

### VerifyExcludes

A list of regex patterns that will match against the incoming event. If matched, then that event will be excluded from the auto-verifier.

```javascript
verifyExcludes : [ "stripe\.", "logout" ],
```

### RotationTimeout

All csrf tokens have a life span of 30 minutes.  But you can control how long they live with this setting.

```javascript
rotationTimeout : 60,
```

### EnableEndpoint

This setting enables the `GET /cbcsrf/generate` endpoint to generate csrf tokens for secured users.  You can use this endpoint to generate user tokens via AJAX or UI-only applications. Please note that you can pass an optional `/:key` URL parameter that will generate the token for that specific key.

{% hint style="danger" %}
**IMPORTANT:** This endpoint is secured via a `secured` annotation, so make sure the firewall has annotation-driven rules enabled.
{% endhint %}

### CacheStorage

The WireBox ID to use for storing the tokens.  The default is the `CacheStorage@cbstorages` object.  However, you can use any ColdBox storage or your own as long as it matches the CBStorages API: <https://forgebox.io/view/cbstorages>.

```javascript
cacheStorage : "SessionStorage@cbstorages"
```

### EnableAuthTokenRotator

This setting is enabled by default and what it does is that it will rotate a user's secret keys when they login/logout via any authentication service registered with CBSecurity.

```javascript
enableAuthTokenRotator : false
```


# JWT

JSON Web Tokens configurations

## Global Configuration

Here is the default configuration for our JSON Web Tokens integration:

```javascript
cbsecurity : {
    /**
     * --------------------------------------------------------------------------
     * Json Web Tokens Settings
     * --------------------------------------------------------------------------
     * Here you can configure the JWT services for operation and storage.  In order for your firewall
     * to leverage JWT authentication/authorization you must make sure you use the `JwtAuthValidator` as your
     * validator of choice; either globally or at the module level.
     */
    jwt                     : {
        // The issuer authority for the tokens, placed in the `iss` claim
        issuer                          : "",
        // The jwt secret encoding key, defaults to getSystemEnv( "JWT_SECRET", "" )
        // This key is only effective within the `config/Coldbox.cfc`. Specifying within a module does nothing.
        secretKey               : getSystemSetting( "JWT_SECRET", "" ),
        // by default it uses the authorization bearer header, but you can also pass a custom one as well.
        customAuthHeader        : "x-auth-token",
        // The expiration in minutes for the jwt tokens
        expiration              : 60, 
        // If true, enables refresh tokens, token creation methods will return a struct instead
        // of just the access token. e.g. { access_token: "", refresh_token : "" }
        enableRefreshTokens        : false,
        // The default expiration for refresh tokens, defaults to 30 days
        refreshExpiration          : 10080,
        // The Custom header to inspect for refresh tokens
        customRefreshHeader        : "x-refresh-token",
        // If enabled, the JWT validator will inspect the request for refresh tokens and expired access tokens
        // It will then automatically refresh them for you and return them back as
        // response headers in the same request according to the customRefreshHeader and customAuthHeader
        enableAutoRefreshValidator : false,
        // Enable the POST > /cbsecurity/refreshtoken API endpoint
        enableRefreshEndpoint      : true,
        // encryption algorithm to use, valid algorithms are: HS256, HS384, and HS512
        algorithm               : "HS512",
        // Which claims neds to be present on the jwt token or `TokenInvalidException` upon verification and decoding
        requiredClaims          : [] ,
        // The token storage settings
        tokenStorage            : {
            // enable or not, default is true
            "enabled"       : true
            // A cache key prefix to use when storing the tokens
            "keyPrefix"     : "cbjwt_", 
            // The driver to use: db, cachebox or a WireBox ID
            "driver"        : "cachebox",
            // Driver specific properties
            "properties"    : {
                cacheName : "default"
            }
        }
    }
}
```

### `issuer`

The issuer authority for the tokens is placed in the `iss` claim of the token. If empty, we will use the `event.buildLink()` to create the issuer. By default, our validators also check that tokens are created by the same issuer.

### `secretKey`

The secret key is used to sign the JWT tokens. By default, it will try to load an environment variable called `JWT_SECRET` , if that setting is also empty, we will auto-generate a secret token that will last as long as the ColdFusion application scope lasts. So technically, your secret will rotate only if a secret is not specified.

Also, this key is ignored in modules. To specify a fixed key to be used in your modules, you will have to configure it by adding a cbsecurity key settings in the `moduleSettings` structure within the `config/Coldbox.cfc`.

{% hint style="success" %}
Your secret key will auto-rotate every application scope rotation. Please note that all tokens used after that scope rotation will automatically become invalid.

Please note that we use the `jwt-cfml` library for encoding/decoding tokens. Please [refer to it's documentation](https://forgebox.io/view/jwt-cfml) in order to leverage RS and ES algorithms with certificates.

<https://forgebox.io/view/jwt-cfml>
{% endhint %}

### `customAuthHeader`

By default, our jwt services will look into the `authorization` header for a bearer token. However, it can also look in a custom header by this name, which defaults to `x-auth-token`. Finally, if not found, it will also look into the `rc` scope for a `rc[ 'x-auth-token' ]` as well.

### `expiration`

The default expiration in minutes for the JWT tokens. Defaults to 60 minutes

### `algorithm`

The encryption algorithm to use for the tokens. The default is **HS512**, but the available ones for are:

* HS256
* HS384
* **HS512**
* RS256
* RS384
* RS512
* ES256
* ES384
* ES512

In the case of the `RS` and `ES` algorithms, asymmetric keys are expected to be provided in unencrypted PEM or JWK format (in the latter case, first deserialize the JWK to a CFML struct). When using PEM, private keys must be encoded in PKCS#8 format.

If your private key is not currently in this format, conversion should be straightforward:

```
$ openssl pkcs8 -topk8 -nocrypt -in privatekey.pem -out privatekey.pk8
```

When decoding tokens, either a public key or certificate can be provided. (If a certificate is provided, the public key will be extracted.)

{% embed url="<https://forgebox.io/view/jwt-cfml>" %}

### `requiredClaims`

This is an array of claim names that each token MUST have in order to be authenticated. If a token comes in but does not have these claims in the payload structure, it will be deemed invalid.

### `tokenStorage`

By default, our JWT services will store tokens in CacheBox for you in order to be able to invalidate them. We ship with two providers for token storage: `db` and `cachebox`.

#### `Enabled`

By default, the token storage is enabled.

#### `KeyPrefix`

The key prefix to use when storing the keys in permanent storage. Defaults to `cbjwt_`

#### `Driver`

The driver to use. It can be either **db** or **cachebox** or your own WireBox Id for using custom storage.

#### `Properties`

A struct of properties to configure each storage with.

## Refresh Token Configuration

Refresh tokens have several configuration items; check them out in our [refresh token configuration section](/jwt/refresh-tokens#refresh-token-configuration).


# Firewall

Configuring the security firewall

Here are the default settings for configuring the security firewall in CBSecurity:

```javascript
/**
 * --------------------------------------------------------------------------
 * 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"                   : "CBAuthValidator@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"  : "",
	// Default Auhtentication Action: override or redirect when a user has not logged in
	"defaultAuthenticationAction" : "redirect",
	// The global invalid authorization event or URI or URL to go if an invalid authorization occurs
	"invalidAuthorizationEvent"   : "",
	// Default Authorization Action: override or redirect when a user does not have enough permissions to access something
	"defaultAuthorizationAction"  : "redirect",
	// Firewall database event logs.
	"logs" : {
		"enabled"    : false,
		"dsn"        : "",
		"schema"     : "",
		"table"      : "cbsecurity_logs",
		"autoCreate" : true
	}
	// Firewall Rules, this can be a struct of detailed configuration
	// or a simple array of inline rules
	"rules"                       : {
		// Use regular expression matching on the rule match types
		"useRegex" : true,
		// Force SSL for all relocations
		"useSSL"   : false,
		// A collection of default name-value pairs to add to ALL rules
		// This way you can add global roles, permissions, redirects, etc
		"defaults" : {},
		// You can store all your rules in this inline array
		"inline"   : [],
		// If you don't store the rules inline, then you can use a provider to load the rules
		// The source can be a json file, an xml file, model, db
		// Each provider can have it's appropriate properties as well. Please see the documentation for each provider.
		"provider" : { "source" : "", "properties" : {} }
	}
},
```

### AutoLoadFirewall

The security firewall is always enabled by default, but you can disable it globally if you like.

```javascript
autoLoadFirewall : false
```

### HandlerAnnotationSecurity

By default, annotation security is enabled. This will inspect ALL incoming event executions for the security annotation `secured`. If you do not want to use annotation security, we recommend you turn it off to avoid the inspection of events.

```javascript
handlerAnnotationSecurity : false
```

### Validator

This global validator will be used to validate authentication/authorization.  The default is `CBAuthValidator@cbsecurity`.  This object needs to match the interface: `cbsecurity.interfaces.ISecurityValidator` .  The available validators we ship are:

* **CBAuth Validator**: this is the default validator, which uses the [cbauth](https://cbauth.ortusbooks.com/) module. It provides authentication and *permission-*&#x62;ased security.
* **CFML Security Validator:** Coldbox security has had this validator since version 1,  and it will talk to the ColdFusion engine's security methods (`cflogin,cflogout`). It provides authentication and *role-based* security.
* **Basic Auth Validator:** This validator secures your app via [basic authentication](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication) browser challenges to incoming requests. It can also work with the `BasicAuthUserService` and provide you a basic user credentials storage within your configuration file.&#x20;
* **JWT Validator**: If you want to use JSON Web Tokens, the JWT Validator provides authorization and authentication by validating incoming access/refresh tokens via headers for RESTFul API communications.
* **Custom Validator:** You can define your own authentication and authorization engines and plug them into the cbsecurity framework.

```javascript
validator : "BasicAuthValidator@cbsecurity"
```

### InvalidAuthenticationEvent

This setting is used to set the global event that will be executed or redirected to if an invalid authentication is detected.  Usually, you want to direct users to a login screen.

```javascript
"invalidAuthenticationEvent"  : "security.login",
```

### DefaultAuthenticationAction

We set the default event above, but how do we get there? This setting is the action the firewall will take when an invalid authentication event is detected. &#x20;

1. `redirect` - Redirect them to the `invalidAuthenticationEvent`
2. `override` - Override the incoming event to the `invalidAuthenticationEvent`
3. `block` - Block the request entirely with a 401 Not Authorized response.

### InvalidAuthorizationEvent

This setting is used to set the global event that will be executed or redirected to if an invalid authorization is detected.  Usually, you could direct them to a not authorized page.

```javascript
"invalidAuthorizationEvent"  : "dashboard.notAuthorized",
```

### DefaultAuthorizationAction

We set the default event above, but how do we get there? This setting is the action the firewall will take when an invalid authorization event is detected. &#x20;

1. `redirect` - Redirect them to the `invalidAuthorizationEvent`
2. `override` - Override the incoming event to the `invalidAuthorizationEvent`
3. `block` - Block the request entirely with a 401 Not Authorized response.

### Logs

You can enable the firewall logs, and CBSecurity will log all blocks the firewall detects.  By default, it is disabled, but if you enable the logs, we will create the table for you.

```javascript
"logs" : {
    "enabled"    : false,
    "dsn"        : "",
    "schema"     : "",
    "table"      : "cbsecurity_logs",
    "autoCreate" : true
}
```

{% hint style="info" %}
The `dsn` key is optional, and CBSecurity will inspect the Application settings for a default datasource.
{% endhint %}

We have also included a migrations file so you can add this to your database migrations schemas.  Just run: `migrate create create_cbsecurity_logs_table` and fill it out with this:

{% code lineNumbers="true" %}

```javascript
component {

	variables.INDEX_COLUMNS = [
		"userId",
		"userAgent",
		"ip",
		"host",
		"httpMethod",
		"path",
		"referer"
	];

	function up( schema, qb ){
		schema.create( "cbsecurity_logs", function( table ){
			table.string( "id", 36 ).primaryKey();
			table.timestamp( "logDate" ).withCurrent();
			table.string( "action" );
			table.string( "blockType" );
			table.string( "ip" );
			table.string( "host" );
			table.string( "httpMethod" );
			table.string( "path" );
			table.string( "queryString" );
			table.string( "referer" ).nullable();
			table.string( "userAgent" );
			table.string( "userId" ).nullable();
			table.longText( "securityRule" ).nullable();
			table.index( [ "logDate", "action", "blockType" ], "idx_cbsecurity" );

			INDEX_COLUMNS.each( ( key ) => {
				table.index( [ arguments.key ], "idx_cbsecurity_#arguments.key#" );
			} );
		} );
	}

	function down( schema, qb ){
		schema.drop( "cbsecurity_logs" );
	}

}
```

{% endcode %}

### Rules

This key defines where rules come from and how they interact with the firewall.  The `rules` key can be of two types:

* An `array` of rules
* A `struct` of configuration with a rule source

#### Array of Rules

This is the shorthand way of defining global rules.

```javascript
"rules" : [
	// should use direct action and do a global redirect
	{
		"whitelist"   : "",
		"securelist"  : "admin",
		"match"       : "event",
		"roles"       : "admin",
		"permissions" : "",
		"action"      : "redirect",
		"httpMethods" : "*"
	},
	// Match only put/post
	{
		"whitelist"   : "",
		"securelist"  : "putpost",
		"match"       : "event",
		"roles"       : "",
		"permissions" : "",
		"action"      : "block",
		"httpMethods" : "put,post"
	},
	{
		"whitelist"   : "",
		"securelist"  : "cfide",
		"match"       : "url",
		"roles"       : "",
		"permissions" : "",
		"action"      : "redirect",
		"allowedIPs"  : "10.0.0.1"
	},
	// no action, use global default action
	{
		"whitelist"   : "",
		"securelist"  : "noAction",
		"match"       : "url",
		"roles"       : "admin",
		"permissions" : "",
		"httpMethods" : "*"
	}
]
```

#### Rule Configuration

If this setting is a struct, you can configure how the rules behave and where they come from JSON, XML, database, model, etc.

<pre class="language-javascript"><code class="lang-javascript"><strong>"rules" : {
</strong>    // Use regular expression matching on the rule match types
    "useRegex" : true,
    // Force SSL for all relocations
    "useSSL"   : false,
    // A collection of default name-value pairs to add to ALL rules
    // This way you can add global roles, permissions, redirects, etc
    "defaults" : {},
    // You can store all your rules in this inline array
    "inline"   : [],
    // If you don't store the rules inline, then you can use a provider to load the rules
    // The source can be a json file, an xml file, model, db
    // Each provider can have it's appropriate properties as well. Please see the documentation for each provider.
    "provider" : { "source" : "", "properties" : {} }
}
</code></pre>

#### useRegex

This is `true` by default.   It tells the firewall to use regular expression matching against white and secure lists in a rule.

#### useSSL

If `true` then if a security rule needs to do a redirect, it will force the redirect to SSL. This defaults to `false`.

#### defaults

This is a collection of name-value pairs that each security rule will inherit by default.

```javascript
defaults : {
    action : "block",
    roles  : "users"
}
```

#### inline

This is an array that holds all the rules you can define in CFML. This is the same as making the entire `rules` key an array of rules.

```javascript
"rules" : {
    // You can store all your rules in this inline array
    "inline"   : [
	// should use direct action and do a global redirect
	{
		"whitelist"   : "",
		"securelist"  : "admin",
		"match"       : "event",
		"roles"       : "admin",
		"permissions" : "",
		"action"      : "redirect",
		"httpMethods" : "*"
	},
	// Match only put/post
	{
		"whitelist"   : "",
		"securelist"  : "putpost",
		"match"       : "event",
		"roles"       : "",
		"permissions" : "",
		"action"      : "block",
		"httpMethods" : "put,post"
	}
    ]
}
```

#### provider

The `provider` key is how you can define rules from the following sources:

* A JSON file
* An XML file
* From a model object via a method call
* From a database

Here are the different ways you can define rules from other sources rather than inline:

{% content-ref url="/pages/-LTJ0k-4j6u9wQ5zwn9d" %}
[DB Rules](/getting-started/configuration/firewall/untitled)
{% endcontent-ref %}

{% content-ref url="/pages/-LTJ1v\_hNnjsikLmqXzv" %}
[JSON Rules](/getting-started/configuration/firewall/json-properties)
{% endcontent-ref %}

{% content-ref url="/pages/-Lp-8TeC7az5DWyOipiQ" %}
[Model Rules](/getting-started/configuration/firewall/model-rules)
{% endcontent-ref %}

{% content-ref url="/pages/-LTJ1uzOrjwuNmxKDcop" %}
[XML Rules](/getting-started/configuration/firewall/xml-properties)
{% endcontent-ref %}

{% hint style="success" %}
Please note that defining rules are both the same in a global ColdBox config as in a ModuleConfig.
{% endhint %}


# DB Rules

Security rules from a database

CBSecurity also allows you to store your security rules in a database as long as all the columns match the keys of the rules as we saw in the [rule anatomy.](/getting-started/overview#rule-anatomy)

You will use the `db` as the `source` and fill out the available db properties:

{% code title="config/Coldbox.cfc" %}

```javascript
// CB Security
cbSecurity : {
  firewall : {
    rules : {
      provider : {
        "source" : "db",
        "properties" : {
            "dsn" : "myapp",
            "sql" : "",
            "table" : "securityRules",
            "orderBy" : "order asc"
        }
      }
    }
  }
}
```

{% endcode %}

* The `dsn` property is the name of the datasource to use
* The `table` property is what table the rules are stored in
* The `orderBy` property is what order by SQL to use, by default it is empty
* The `sql` property is what SQL to execute to retrieve the rules.  The default is `select * from ${table}`<br>


# JSON Rules

Security rules in a JSON file

You can place all your security rules inside of a JSON file and then tell CBSecurity where they are:

{% code title="config/Coldbox.cfc" %}

```javascript
// CB Security
cbSecurity : {
  firewall : {
    rules : {
      provider : {
        "source" : "config/security.json.cfm"
      }
    }
  }
}
```

{% endcode %}

Then your file can be something like this:

{% code title="config/security.json.cfm" %}

```javascript
[
    {
        "whitelist": "user\\.login,user\\.logout,^main.*",
        "securelist": "^user\\.*, ^admin",
        "match": "event",
        "roles": "admin",
        "permissions": "",
        "redirect": "user.login",
        "useSSL": false
    },
    {
        "whitelist": "",
        "securelist": "^shopping",
        "match": "url",
        "roles": "",
        "permissions": "shop,checkout",
        "redirect": "user.login",
        "useSSL": true
    }
]
```

{% endcode %}


# Model Rules

Security rules from a model's method call

If you prefer to store your rules your way, CBSecurity can talk to any WireBox ID or model and get the rules from them by using the `model` source in the rule provider.

{% code title="config/Coldbox.cfc" %}

```javascript
// CB Security
cbSecurity : {
  firewall : {
    rules : {
      provider : {
        "source" : "model",
        "properties" : {
            "model" : "SecurityService",
            "method" : "getSecurityRules"
        }
      }
    }
  }
}
```

{% endcode %}

* The `model` property is any WireBox ID or classpath
* The `method` property is the name of the method to call to get an array of rules back<br>


# XML Rules

Security rules in an XML file

You can place all your security rules inside of an XML file and then tell CBSecurity where they are:

{% code title="config/Coldbox.cfc" %}

```javascript
// CB Security
cbSecurity : {
  firewall : {
    rules : {
      provider : {
        "source" : "config/security.xml.cfm"
      }
    }
  }
}
```

{% endcode %}

Then your XML file can look like this:

{% code title="config/security.xml.cfm" %}

```markup
<?xml version="1.0" encoding="ISO-8859-1"?>
<-- <
Declare as many rule elements as you want, order is important 
Remember that the securelist can contain a list of regular
expressions if you want

ex: All events in the user handler
 user\..*
ex: All events
 .*
ex: All events that start with admin
 ^admin

If you are not using regular expressions, just write the text
that can be found in an event.
-->
<rules>
    <rule>
        <match>event</match>
        <whitelist>user\.login,user\.logout,^main.*</whitelist>
        <securelist>^user\..*, ^admin</securelist>
        <roles>admin</roles>
        <permissions>read,write</permissions>
        <redirect>user.login</redirect>
    </rule>

    <rule>
        <match>event</match>
        <whitelist></whitelist>
        <securelist>^moderator</securelist>
        <roles>admin,moderator</roles>
        <permissions>read</permissions>
        <redirect>user.login</redirect>
    </rule>

    <rule>
        <match>url</match>
        <whitelist></whitelist>
        <securelist>/secured.*</securelist>
        <roles>admin,paid_subscriber</roles>
        <permissions></permissions>
        <redirect>user.pay</redirect>
    </rule>
</rules>
```

{% endcode %}


# Security Headers

Configuring the security response headers and features

CBSecurity comes bundled with tons of security response features to help developers be secure-minded about their applications.  Here are the defaults for configuring the security headers in CBSecurity.

<pre class="language-javascript" data-line-numbers><code class="lang-javascript">/**
 * --------------------------------------------------------------------------
 * Security Headers
 * --------------------------------------------------------------------------
 * This section is the way to configure cbsecurity for header detection, inspection and setting for common
 * security exploits like XSS, ClickJacking, Host Spoofing, IP Spoofing, Non SSL usage, HSTS and much more.
 */
securityHeaders : {
<strong>	// If you trust the upstream then we will check the upstream first for specific headers
</strong>	"trustUpstream"         : false,
	// Content Security Policy
	// Content Security Policy (CSP) is an added layer of security that helps to detect and mitigate certain types of attacks,
	// including Cross-Site Scripting (XSS) and data injection attacks. These attacks are used for everything from data theft, to
	// site defacement, to malware distribution.
	// https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
	"contentSecurityPolicy" : {
		// Disabled by defautl as it is totally customizable
		"enabled" : false,
		// The custom policy to use, by default we don't include any
		"policy"  : ""
	},
	// The X-Content-Type-Options response HTTP header is a marker used by the server to indicate that the MIME types advertised in
	// the Content-Type headers should be followed and not be changed => X-Content-Type-Options: nosniff
	// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options
	"contentTypeOptions" : { "enabled" : true },
	"customHeaders"      : {
		 // Name : value pairs as you see fit.
	},
	// Disable Click jacking: X-Frame-Options: DENY OR SAMEORIGIN
	// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
	"frameOptions" : { "enabled" : true, "value" : "SAMEORIGIN" },
	// HTTP Strict Transport Security (HSTS)
	// The HTTP Strict-Transport-Security response header (often abbreviated as HSTS)
	// informs browsers that the site should only be accessed using HTTPS, and that any future attempts to access it
	// using HTTP should automatically be converted to HTTPS.
	// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security,
	"hsts"         : {
		"enabled"           : true,
		// The time, in seconds, that the browser should remember that a site is only to be accessed using HTTPS, 1 year is the default
		"max-age"           : "31536000",
		// See Preloading Strict Transport Security for details. Not part of the specification.
		"preload"           : false,
		// If this optional parameter is specified, this rule applies to all of the site's subdomains as well.
		"includeSubDomains" : false
	},
	// Validates the host or x-forwarded-host to an allowed list of valid hosts
	"hostHeaderValidation" : {
		"enabled"      : false,
		// Allowed hosts list
		"allowedHosts" : ""
	},
	// Validates the ip address of the incoming request
	"ipValidation" : {
		"enabled"    : false,
		// Allowed IP list
		"allowedIPs" : ""
	},
	// The Referrer-Policy HTTP header controls how much referrer information (sent with the Referer header) should be included with requests.
	// Aside from the HTTP header, you can set this policy in HTML.
	// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy
	"referrerPolicy"     : { "enabled" : true, "policy" : "same-origin" },
	// Detect if the incoming requests are NON-SSL and if enabled, redirect with SSL
	"secureSSLRedirects" : { "enabled" : false },
	// Some browsers have built in support for filtering out reflected XSS attacks. Not foolproof, but it assists in XSS protection.
	// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection,
	// X-XSS-Protection: 1; mode=block
	"xssProtection"      : { "enabled" : true, "mode" : "block" }
}
</code></pre>

### TrustUpstream

This boolean flag tells CBSecurity whether to inspect `x-forwarded-` headers FIRST instead of traditional host/IP headers.  If you trust your proxies, then turn this setting to `true`.

### ContentSecurityPolicy

The Content Security Policy (CSP) is an added layer of security that helps to detect and mitigate certain types of attacks, including Cross-Site Scripting (XSS) and data injection attacks. These attacks are used for data theft, site defacement, and malware distribution. &#x20;

By default, this policy is disabled as it requires a custom policy to be written according to your needs.  Once you have a policy available, you can add it to the configuration.

{% embed url="<https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP>" %}
Read more about content security policies
{% endembed %}

```javascript
"contentSecurityPolicy" : {
    // Disabled by defautl as it is totally customizable
    "enabled" : true,
    // The custom policy to use, by default we don't include any
    "policy"  : "default-src 'self' *.example.com; img-src *"
},
```

### ContentTypeOptions

The `X-Content-Type-Options` response HTTP header is a marker used by the server to indicate that the MIME types advertised in the `Content-Type` headers should be followed and not be changed.  This produces the following header => `X-Content-Type-Options: nosniff` &#x20;

{% embed url="<https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options>" %}
Read more about content type options
{% endembed %}

```javascript
"contentTypeOptions" : { "enabled" : true },
```

### CustomHeaders

You can fill out this struct with the custom headers you would like to send out on EVERY request.  The header value can be a simple value to return always or a closure/lambda that will be executed at runtime and the value sent on every request.

```javascript
customHeaders : {
    "x-mvc" : "ColdBox",
    "x-runtime-timestamp" : (event,rc,prc) => now()
}
```

Please note that the closure accepts the incoming `event, rc, and prc` variables.

### FrameOptions

The **`X-Frame-Options`** [HTTP](https://developer.mozilla.org/en-US/docs/Web/HTTP) response header can be used to indicate whether or not a browser should be allowed to render a page in a [`<frame>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/frame), [`<iframe>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe), [`<embed>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/embed) or [`<object>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/object). Sites can use this to avoid [click-jacking](https://developer.mozilla.org/en-US/docs/Web/Security/Types_of_attacks#click-jacking) attacks by ensuring that their content is not embedded into other sites.  The default value ColdBox uses is `SAMEORIGIN` which allows iframes and embeds from the same origin.  The available values are: `SAMEORIGIN OR DENY`.

{% embed url="<https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options>" %}
Read more about frame options
{% endembed %}

```javascript
"frameOptions" : { "enabled" : true, "value" : "SAMEORIGIN" },
```

### HSTS - HTTP Strict Transport Security

The HTTP Strict-Transport-Security response header (often abbreviated as HSTS) informs browsers that the site should only be accessed using HTTPS and that any future attempts to access it using HTTP should automatically be converted to HTTPS.  Here are the defaults we use in CBSecurity:

{% embed url="<https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security>" %}
Read more about HSTS
{% endembed %}

```javascript
"hsts" : { 
    "enabled" : true, 
    // The time, in seconds, that the browser should remember that a site is only to 
    // be accessed using HTTPS, 1 year is the default 
    "max-age" : "31536000", 
    // See Preloading Strict Transport Security for details. Not part of the specification. 
    "preload" : false, 
    // If this optional parameter is specified, this rule applies to all of the site's subdomains as well. 
    "includeSubDomains" : false 
},
```

### HostHeaderValidation

This configuration setting can restrict access to your application for ONLY a specific list of hosts.  This prevents host spoofing.  If an invalid host is detected, a 401 Not Authorized response will be sent back to the user.  This setting is **disabled** by default.

```javascript
// Validates the host or x-forwarded-host to an allowed list of valid hosts
"hostHeaderValidation" : {
	"enabled"      : true,
	// Allowed hosts list
	"allowedHosts" : "www.coldbox.org,coldbox.org"
},
```

### IPValidation

This configuration setting can restrict access to your application for ONLY a specific list of IP addresses.  This prevents IP spoofing.  If an invalid IP is detected, then a 401 Not Authorized response will be sent back to the user.  This setting is **disabled** by default.

{% hint style="warning" %}
Please note that as of now, a full IP address must be used.
{% endhint %}

```javascript
// Validates the host or x-forwarded-host to an allowed list of valid hosts
"ipValidation" : {
	"enabled"      : true,
	// Allowed hosts list
	"allowedHosts" : "127.0.0.1,98.98.98.98"
},
```

### ReferrerPolicy

The Referrer-Policy HTTP header controls how much referrer information (sent with the Referer header) should be included with requests.  Aside from the HTTP header, you can set this policy in HTML.  This setting is **enabled** by default with a policy of `same-origin`.

{% embed url="<https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy>" %}
Read more about referrer policies
{% endembed %}

```javascript
"referrerPolicy"     : { 
    "enabled" : true, 
    "policy" : "same-origin" 
},
```

Here are some available policies:

```
Policy: no-referrer
Policy: no-referrer-when-downgrade
Policy: origin
Policy: origin-when-cross-origin
Policy: same-origin
Policy: strict-origin
Policy: strict-origin-when-cross-origin
Policy: unsafe-url
```

### SecureSSLRedirects

Detect if the incoming requests are NON-SSL and redirect with SSL alongside any incoming query strings and host information if enabled.  By default, this setting is **disabled**.

```javascript
"secureSSLRedirects" : { "enabled" : true },
```

### XSSProtection

Some browsers have built-in support for filtering out reflected XSS attacks. Not foolproof, but it assists in XSS protection.  By default, it is **enabled** and a `block` mode is produced.

{% embed url="<https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection>" %}
Read more about XSS protection
{% endembed %}

```javascript
"xssProtection"      : { 
    "enabled" : true, 
    "mode" : "block" 
}
```


# Visualizer

Configuring the CBSecurity Visualizer

The CBSecurity visualizer is a tool that will allow you to visualize all of your configuration settings, firewall logs, and much more.  By default, the visualizer is **disabled**.

<figure><img src="/files/OjZfy4YhJNDPmw4AyyvK" alt=""><figcaption><p>Visualizer</p></figcaption></figure>

{% hint style="danger" %}
If you enable the visualizer, we highly suggest you **secure** it.
{% endhint %}

If enabled, you can visit the `/cbsecurity` entry point, and you will get the visualizer rendered. &#x20;

## Configuration

Here are the configuration settings for the visualizer:

```javascript
/**
* --------------------------------------------------------------------------
* Security Visualizer
* --------------------------------------------------------------------------
* This is a debugging panel that when active, a developer can visualize security settings and more.
* You can use the `securityRule` to define what rule you want to use to secure the visualizer but make sure the `secured` flag is turned to true.
* You don't have to specify the `secureList` key, we will do that for you.
*/
visualizer : {
	"enabled"      : false,
	"secured"      : false,
	"securityRule" : {}
},
```

### enabled

If `false` then no visualizer, if `true` then you get a visualizer :tada:

### secured

We highly encourage you to ensure the visualizer is ONLY accessible if you have authenticated into your system.  By using a `secured=true` then CBSecurity will incorporate a rule to secure the visualizer for ONLY authenticated users.  If you want to be picky, use the `securityRule` setting.

### securityRule

We also recommend that ONLY certain users have access to the visualizer. You can accomplish this by adding the keys to the security rule created for the visualizer.  For example, I only want `admins` or users with the `cbsecurity-visualizer` permission to access it.

```javascript
visualizer : {
	"enabled"      : true,
	"secured"      : true,
	"securityRule" : {
		"roles" : "admins",
		"permissions" : "cbsecurity-visualizer"
	}
}
```

## Requirements

Please note that the security visualizer can ONLY visualize if you have [firewall logs enabled](/getting-started/configuration/firewall#logs).  If no logs are enabled or configured, then the visualizer WILL NOT WORK.  Here is a simple logs configuration in the firewall

```javascript
firewall : {

    "logs" : {
        "enabled"    : true,
        "dsn"        : "myapp",
        "schema"     : "",
        "table"      : "cbsecurity_logs",
        "autoCreate" : true
    }
    
}
```

{% hint style="warning" %}
The `dsn` key is optional, and CBSecurity will inspect the Application.cfc settings for a default datasource: `this.datasource`
{% endhint %}


# Authentication Services

ColdBox security can work with ANY authentication service provider.

CBSecurity has been designed to work with **ANY** authentication and user service provider. CBSecurity is in charge of intercepting requests and delegating access verification to *Security Validators*, leveraging *Authentication* and *User Services* to allow access to a resource or block the request ultimately.

<figure><img src="/files/Mu1EuJ5mHSOQayZQD7tF" alt=""><figcaption><p>The CBSecurity Security Flow</p></figcaption></figure>

We have created an [interface](#authentication-service-interface) that must be implemented by any service that is going to be used with CBSecurity: `cbsecurity.interfaces.IAuthService`. Then you would configure this service in the [Configuration](/getting-started/configuration/authentication) File alongside the validator you would like to use (cbauth, JWT, basic auth, etc.)

```javascript
/**
 * --------------------------------------------------------------------------
 * 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"     : cbauth.userServiceclass,
	// The name of the variable to use to store an authenticated user in prc scope on all incoming authenticated requests
	"prcUserVariable" : "oCurrentUser"
},

firewall : {
        "validator" : "CBAuthValidator@cbsecurity"
}
```

By default, CBSecurity ships with a very simple yet powerful authentication service and validator called [cbauth](https://forgebox.io/view/cbauth). This module gives you the ability to login, logout, verify and tracker users across requests using session and request storages. All you have to do is provide a User Service class that will connect to your storage of choice in order to operate. Here is a typical `cbauth` configuration that will exist alongside the `cbsecurity` module settings:

```javascript
cbauth = {
    // This is the path to your user object that contains the credential validation methods
    userServiceClass = "MyUserService"
},
```

This user service must also adhere to our User Service interface: `cbsecurity.interfaces.IUserService` and the user objects it must produce also will need to adhere to our user interface: `cbsecurity.interface.IAuthUser`.

If you are using `cbauth`, please keep in mind that it stores only the user id in session. All other `AuthUser` properites are transient as they are part of the request scope.

## IAuthService

This interface has been provided by convenience, and it is not mandatory at runtime since cbauth implements it: (`cbsecurity.interfaces.IAuthService`)

{% code title="cbsecurity.interfaces.IAuthService.cfc" %}

```javascript
/**
 * Copyright since 2016 by Ortus Solutions, Corp
 * www.ortussolutions.com
 * ---
 * If you register an authentication service with cbsecurity it must adhere to this interface
 */
interface{

    /**
     * Get the authenticated user
     *
     * @throws NoUserLoggedIn : If the user is not logged in
     *
     * @return User that implements IAuthUser
     */
    any function getUser();

    /**
     * Verifies if a user is logged in
     */
    boolean function isLoggedIn();

    /**
     * Try to authenticate a user into the system. If the authentication fails an exception is thrown, else the logged in user object is returned
     *
     * @username The username to log in with
     * @password The password to log in with
     *
     * @throws InvalidCredentials 
     *
     * @return User : The logged in user object
     */
    any function authenticate( required username, required password );

    /**
    * Login a user into our persistent scopes
    *
    * @user The user object to log in
    *
    * @return The same user object so you can do functional goodness
    */
    function login( required user );

    /**
     * Logs out the currently logged in user from the system
     */
    function logout();


}
```

{% endcode %}

You can find the information for **cbauth** in its book:

{% embed url="<https://cbauth.ortusbooks.com>" %}

## IAuthUser

As you can see from above, the authentication services all expect a `User` object to model your user in the system. So your `User` object must also adhere to the following methods modeled by the `cbsecurity.interfaces.IAuthUser` interface. This will allow the validators and JWT services to get the appropriate data.

{% code title="cbsecurity.interfaces.IAuthUser.cfc" %}

```javascript
/**
 * Copyright since 2016 by Ortus Solutions, Corp
 * www.ortussolutions.com
 * ---
 * If you use a user with a user service or authentication service, it must implement this interface
 */
interface{

    /**
     * Return the unique identifier for the user
     */
    function getId();

    /**
     * Verify if the user has one or more of the passed in permissions
     *
     * @permission One or a list of permissions to check for access
     *
     */
    boolean function hasPermission( required permission );

	/**
     * Verify if the user has one or more of the passed in roles
     *
     * @role One or a list of roles to check for access
     *
     */
    boolean function hasRole( required role );

}
```

{% endcode %}

## IUserService

If you are using **cbauth** or any of our JWT features, then we will also require you to register a user service class that can provide us with the correct data to encapsulate security using the `userService` setting. We have provided this interface for your usage:

{% code title="cbsecurity.interfaces.IUserService.cfc" %}

```javascript
interface{

    /**
     * Verify if the incoming username/password are valid credentials.
     *
     * @username The username
     * @password The password
     */
    boolean function isValidCredentials( required username, required password );

    /**
     * Retrieve a user by username
     *
     * @return User that implements JWTSubject and/or IAuthUser
     */
    function retrieveUserByUsername( required username );

    /**
     * Retrieve a user by unique identifier
     *
     * @id The unique identifier
     *
     * @return User that implements JWTSubject and/or IAuthUser
     */
    function retrieveUserById( required id );
}
```

{% endcode %}

## Simple Example

Ok, now that we have discovered the basics of CBSecurity, why don't we build a simple example using a database-driven approach to security with `cbauth`. Please note that we also have a [Basic Authentication](/usage/basic-authentication) approach as well.

### Configuration

We will use the defaults CBSecurity ships with to protect our new admin console with `cbauth`.

```javascript
moduleSettings : {
    cbauth : {
        // Our service class
	userServiceClass : "UserService"
    },
	
    cbsecurity : {
        // The global invalid authentication event or URI or URL to go if an invalid authentication occurs
	"invalidAuthenticationEvent"  : "security.login",
	// Default Auhtentication Action: override or redirect when a user has not logged in
	"defaultAuthenticationAction" : "redirect",
	// The global invalid authorization event or URI or URL to go if an invalid authorization occurs
	"invalidAuthorizationEvent"   : "security.notAuthorized",
	// Default Authorization Action: override or redirect when a user does not have enough permissions to access something
	"defaultAuthorizationAction"  : "redirect",
	// Firewall database event logs.
	"logs" : {
		"enabled"    : true,
		"table"      : "cbsecurity_logs"
	},
	rules : [
	    {
		    secureList : "^admin"
	    }
	]
    }
};
```

As you can see, we don't have to specify an authentication provider or validator; it's already defaulted to `cbauth`. I only have to specify the user service that will provide the `User` object and user information from my database.

### User

Ok, before I go into building my user service, I would have to create a `User` object that the service would return so `cbauth` can use it. However, `CBSecurity` already ships with a basic authentication user object I can use: `cbsecurity.models.basicauth.BasicAuthUser`.

I will model my database table after it and create the following columns:

* `id`
* `firstName`
* `lastName`
* `username`
* `password`
* `permissions`
* `roles`

```javascript
/**
 * This is a basic user object that can be used with cbsecurity.
 * It implements the following interfaces
 * - cbsecurity.interfaces.jwt.IJwtSubject
 * - cbsecurity.interfaces.IAuthUser
 */
component accessors="true" {

	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;
	}

	function setRoles( roles ){
		if ( isSimpleValue( arguments.roles ) ) {
			arguments.roles = listToArray( arguments.roles );
		}
		variables.roles = arguments.roles;
		return this;
	}

	function setPermissions( permissions ){
		if ( isSimpleValue( arguments.permissions ) ) {
			arguments.permissions = listToArray( arguments.permissions );
		}
		variables.permissions = arguments.permissions;
		return this;
	}

	/**
	 * Verify if this is a valid user or not
	 */
	boolean function isLoaded(){
		return ( !isNull( variables.id ) && len( variables.id ) );
	}

	/**
	 * A struct of custom claims to add to the JWT token
	 */
	struct function getJWTCustomClaims( required struct payload ){
		return { "role" : variables.roles.toList() };
	}

	/**
	 * This function returns an array of all the scopes that should be attached to the JWT token that will be used for authorization.
	 */
	array function getJWTScopes(){
		return variables.permissions;
	}

	/**
	 * Verify if the user has one or more of the passed in permissions
	 *
	 * @permission One or a list of permissions to check for access
	 */
	boolean function hasPermission( required permission ){
		if ( isSimpleValue( arguments.permission ) ) {
			arguments.permission = listToArray( arguments.permission );
		}

		return arguments.permission
			.filter( function( item ){
				return ( variables.permissions.findNoCase( item ) );
			} )
			.len();
	}

	/**
	 * Verify if the user has one or more of the passed in roles
	 *
	 * @role One or a list of roles to check for access
	 */
	boolean function hasRole( required role ){
		if ( isSimpleValue( arguments.role ) ) {
			arguments.role = listToArray( arguments.role );
		}

		return arguments.role
			.filter( function( item ){
				return ( variables.roles.findNoCase( item ) );
			} )
			.len();
	}

}

```

### User Service

Ok, now let's build our basic service that will leverage the DB and simple password hashing. Remember, this object must implement `cbsecurity.interfaces.IUserService` :

```javascript
component accessors="true" singleton {

	/*********************************************************************************************/
	/** DI **/
	/*********************************************************************************************/

	property name="populator" inject="wirebox:populator";
	property name="wirebox"   inject="wirebox";

	/*********************************************************************************************/
	/** Static Settings **/
	/*********************************************************************************************/

	static {
		hashAlgorithm = "SHA-512";
		hashIterations = 5;
	}

	/**
	 * Constructor
	 */
	function init(){
		return this;
	}

	/**
	 * Hash the incoming target according to our hashing algorithm and settings
	 * @target The string target to hash
	 */
	private string function hashSecurely( required string target ){
		return hash( arguments.target, static.hashAlgorithm, "UTF-8", static.hashIterations );
	}

	/**
	 * New User Dispenser
	 */
	BasicAuthUser function new() provider="BasicAuthUser@cbsecurity"{
	}

	/**
	 * Get a new user by id
	 *
	 * @id The id to get the user with
	 *
	 * @return The located user or a new un-loaded user object
	 */
	BasicAuthUser function retrieveUserById( required id ){
		return queryExecute( 
			"select * from users where id = :id",
			{ id : arguments.id },
			{ returnType : "array" }
		).reduce( ( result, data ) =>{
			return populator.populateFromStruct( new(), arguments.data );
		}, new() );
	}

	/**
	 * Get a user by username
	 *
	 * @username The username to get the user with
	 *
	 * @return The valid user object representing the username or an empty user object
	 */
	BasicAuthUser function retrieveUserByUsername( required username ){
		return queryExecute( 
			"select * from users where username = :username",
			{ username : arguments.username },
			{ returnType : "array" }
		).reduce( ( result, data ) =>{
			return populator.populateFromStruct( new(), arguments.data );
		}, new() );
	}

	/**
	 * Verify if the incoming username and password are valid credentials in this user storage
	 *
	 * @username The username to test
	 * @password The password to test
	 *
	 * @return true if valid, else false
	 */
	boolean function isValidCredentials( required username, required password ){
		var oUser = retrieveUserByUsername( arguments.username );
		if ( !oUser.isLoaded() ) {
			return false;
		}

		return hashSecurely( arguments.password ) eq oUser.getPassword();
	}

}

```

### Testing It Out

At this point, I have satisfied all the requirements for CBSecurity to work:

1. Create a user service that knows how to get users by id, username, and credentials
2. Created my database table and connection

Now I have to build out:

1. Login screen
2. Login processor
3. Logout processor

#### Login Handler and Screen

```javascript
component{
    function login( event, rc, prc ){
        event.setView( "security.login" );
    }
}
```

```html
<cfoutput>
<h1>Security Login</h1>

<cfif flash.exists( "message" )>
  <div style="border: 1px solid gray; background-color: ##f29595; margin: 20px 0px; padding: 10px">
	#flash.get( "message" )#
  </div>
</cfif>

#html.startForm( action="security.doLogin" )#

  #html.textField( name="username", placeholder="username" )#
  <br>
  #html.passwordField( name="password", placeholder="password" )#
  <br>
  #html.submitButton( name="Submit" )#

#html.endForm()#
</cfoutput>
```

#### Login-Logout Processor

```javascript
component{
    function doLogin( event, rc, prc ){
        try {
	    var oUser = cbsecure().authenticate( rc.username ?: "", rc.password ?: "" );
	    return "You are logged in!";
	} catch ( "InvalidCredentials" e ) {
	    flash.put( "message", "Invalid credentials, try again!" );
	    relocate( "security/login" );
	}
    }
    
    function doLogout( event, rc, prc ){
	cbsecure().logout();
	flash.put( "message", "Bye bye!" );
	relocate( "security/login" );
    }
}
```

{% hint style="info" %}
You can also use the `guest()` method to verify if the user is NOT logged in.
{% endhint %}


# Basic Authentication

Basic access authentication is a method for an HTTP user agent (e.g. a web browser) to provide a user name and password when making a request.

CBSecurity supports the concept of HTTP [basic authentication](https://en.wikipedia.org/wiki/Basic_access_authentication) in your ColdBox applications.  Please note that this is a quick and easy way to provide security, but not the safest by any means.  You have been warned!

### What is Basic Authentication?

In the context of an [HTTP](https://en.wikipedia.org/wiki/HTTP) transaction, basic access authentication is a method for an [HTTP user agent](https://en.wikipedia.org/wiki/User_agent) (e.g. a [web browser](https://en.wikipedia.org/wiki/Web_browser)) to provide a username and password when making a request. In basic HTTP authentication, a request contains a header field in the form of `Authorization: Basic <credentials>`, where credentials is the [Base64](https://en.wikipedia.org/wiki/Base64) encoding of ID and password joined by a single colon `:`.

<figure><img src="/files/0BhGytBZ5Q3uca5O9Mtk" alt=""><figcaption><p>Basic Authentication Flow</p></figcaption></figure>

{% hint style="info" %}
HTTP Basic authentication (BA) implementation is the most straightforward technique for enforcing access controls to web resources because it does not require cookies, session identifiers, or login pages; instead, HTTP Basic authentication uses standard fields in the HTTP header.
{% endhint %}

### Configuration

The first step is configuring your application to use [basic authentication](/getting-started/configuration/basic-auth) as the [validator](/security-validators/basicauth-validator) of choice.  We will configure two things:

* Validator: `BasicAuthValidator@cbsecurity`
* Basic auth settings: Where you configure users, passwords, roles, permissions, and encryption

CBSecurity allows you to use basic authentication with ANY authentication service.

```javascript
cbsecurity : {
    
    basicAuth : {
	users : {
	  "lmajano" : { password : 'test', permissions : "", roles : "admin" }
	}
    },
    
    firewall : {
        // Global Relocation when an invalid access is detected, instead of each rule declaring one.
        "invalidAuthenticationEvent" : "main.index",
        // Default invalid action: override or redirect when an invalid access is detected, default is to redirect
        "defaultAuthenticationAction" : "redirect",
        // Global override event when an invalid access is detected, instead of each rule declaring one.
        "invalidAuthorizationEvent"  : "main.index",
        // Default invalid action: override or redirect when an invalid access is detected, default is to redirect
        "defaultAuthorizationAction" : "redirect",
        // Firewall Validator
        "validator"                   : "BasicAuthValidator@cbsecurity"
    }

}
```

This is the *most* basic configuration where we register a single user and tell the firewall to use the basic auth validator.  Since the default authentication service is `cbauth` I don't have to register it.  Finally, since CBSecurity detects the `BasicAuthValidator`and no registered user class, it will register the `BasicAuthUserService` as well for you.

{% hint style="success" %}
You can explicitly set the `UserServiceClass` to be `BasicAuthUserService@cbsecurity` if you wanted to.
{% endhint %}

<figure><img src="/files/T5KB9YPyqXtAgZZGi2JR" alt=""><figcaption><p>Basic Authentication Prompt</p></figcaption></figure>

All I have to do now is create [security rules](/usage/untitled-1) or [annotations](/usage/security-annotations), and CBSecurity will leverage the browser's Basic Authentication Prompt when those resources are trying to be accessed.  Once you put in your credentials, it will verify them against the registered users in the `basicAuth` configuration dictionary.

### Logout

Since Basic Authentication ONLY focuses on login, logout is left out of the equation.  In CBSecurity, we have created a special event so you can securely log out users from basic authentication, which you can hit with ANY HTTP verb.

```
/cbsecurity/basicauth/logout
```

This will call the `logout` method of the authentication service and set the following HTTP headers for you so your session can be rotated:

```javascript
event
    .setHTTPHeader( name = "WWW-Authenticate", value = "basic realm='Please enter your credentials'" )
    .setHTTPHeader( name = "Cache-Control", value = "no-cache, must-revalidate, max-age=0" )
    .renderData( data = "<h1>Logout Successful!</h1>", statusCode = 401 );
```

Ultimately, you can close your browser too.

### ColdBox Request Context

ColdBox also supports the concept of basic authentication retrieval since the early version 2 days.  ColdBox can detect, parse and give you a struct of `username` and `password` by leveraging the request context's `getHTTPBasicCredentials()` method.

```javascript
function preHandler( event, action, eventArguments ){
    var authDetails = event.getHTTPBasicCredentials();
    if( !securityService.authenticate( authDetails.username, authDetails.password ) ) {
        event.renderData( type="JSON", data={ message = 'Please check your credentials' }, statusCode=401, statusMessage="You're not authorized to do that");
    }
}
```

{% embed url="<https://coldbox.ortusbooks.com/digging-deeper/recipes/building-rest-apis#basic-http-auth>" %}
ColdBox HTTP Basic Auth Support
{% endembed %}


# Security Rules

CBSecurity can apply security rules to incoming events.

We have seen by now that rules can be defined in disk, databases, or created at runtime.  These security rules all share a common anatomy and processing; let's explore it.

## Rule Anatomy

A `struct` models each rule with keys in it internally in CBSecurity.  So no matter where these rules come from, at the end of the day, they are registered as an array of structs internally.

```javascript
{
	"id"            : created automatically as a UUID,
	// A list of white list events or Uri's
	"whiteList"     : "", 
	// A list of secured list events or Uri's
	"secureList"    : "", 
	// Match the event or a url
	"match"         : "event", 
	// Attach a list of roles to the rule
	"roles"         : "", 
	// Attach a list of permissions to the 
	"permissions"   : "", rule
	// If rule breaks, and you have a redirect it will redirect here
	"redirect"      : "", 
	// If rule breaks, and you have an event, it will override it
	"overrideEvent" : "", 
	// Force SSL,
	"useSSL"        : false, 
	// The action to use (redirect|override|block) when no redirect or overrideEvent is defined in the rule.
	"action"        : "", 
	// metadata we can add so mark rules that come from modules
	"module"        : "", 
	// Match all HTTP methods or particular ones as a list
	"httpMethods"   : "*",
	// The rule only matches if the IP list matches. It can be a list of IPs to match. 
	"allowedIPs"    : "*" 
}
```

The only required key is the `secureList` which is what you are trying to secure. The rest are optional.

{% hint style="success" %}
Please note that you can add as many extra keys as you like to your security rules structure, which can contain much more context and information for the validators to use for validation.  These are the ones we suggest you add and are used internally.
{% endhint %}

{% hint style="warning" %}
Please remember that by default, the secure and white lists are evaluated as regular expressions. You can turn that off in your [configuration settings.](/getting-started/configuration)
{% endhint %}

### Rule Elements

<table><thead><tr><th width="189">Property</th><th width="112.33333333333331">Type</th><th width="158" align="center">Default</th><th>Description</th></tr></thead><tbody><tr><td><code>action</code></td><td><code>string</code></td><td align="center"><em>empty</em></td><td>The action to use (<code>redirect</code> or <code>override</code> or <code>block</code>) when no explicit <code>overrideEvent</code> or <code>redirect</code> elements are defined.  If not set, then we use the global settings.</td></tr><tr><td><code>allowedIPs</code></td><td><code>string</code></td><td align="center"><code>*</code></td><td>The rule only matches if the IP list matches. It can be a list of IPs to match. By default, it matches all incoming IPs.</td></tr><tr><td><code>httpMethods</code></td><td><code>string</code></td><td align="center"><code>*</code></td><td>Match all HTTP methods or particular ones as a list. By default, it matches all HTTP Methods.</td></tr><tr><td><code>id</code></td><td><code>uuid</code></td><td align="center"><code>createUUID()</code></td><td>The internal ID of the rule.  We automatically assign a UUID to the rule upon registration.</td></tr><tr><td><code>match</code></td><td><code>event</code> or <code>URL</code></td><td align="center"></td><td>Determines if it needs to match the incoming URL or the incoming event. By default it matches the incoming event.</td></tr><tr><td><code>module</code></td><td><code>string</code></td><td align="center"><em>empty</em></td><td>The name of the module this rule belongs to. Empty if none is discovered.</td></tr><tr><td><code>overrideEvent</code></td><td><code>string</code></td><td align="center"></td><td>The event to override using ColdBox's <code>event.overrideEvent()</code> if the user if not authenticated or authorized</td></tr><tr><td><code>permissions</code></td><td><code>string</code></td><td align="center"></td><td>A comma delimited list of permissions that can access these secure events</td></tr><tr><td><code>redirect</code></td><td><code>string</code></td><td align="center"></td><td>An event or route to redirect if the user is not authenticated or authorized</td></tr><tr><td><code>roles</code></td><td><code>string</code></td><td align="center"></td><td>A comma delimited list of roles that can access these secure events</td></tr><tr><td><code>securelist</code></td><td><code>string</code></td><td align="center"></td><td>A comma delimited list of events or regex patterns to secure</td></tr><tr><td><code>whitelist</code></td><td><code>string</code></td><td align="center"></td><td>A comma delimited list of events or regex patterns to whitelist or to bypass security on if a match is made on the <code>secureList</code></td></tr><tr><td><code>useSSL</code></td><td><code>boolean</code></td><td align="center"></td><td>If true, force SSL, else use whatever the request protocol is</td></tr></tbody></table>

##

## Rules processing

When processing rules, it is essential to realize these rules are stored as an array that will be processed in **order**, so make sure your more specific rules will be processed **before** the more generic ones.

![cbsecurity rules processing](/files/-M8karM9MbAuAc7TQtbK)

##

## Rule Overrides

As we saw from the overview and our configuration sections. We can declare the default actions for authorizations and authentication issues and to which events/URLs to go if that happens. There can be a time when you can override those global/module settings directly within a rule. Let's explore these overrides:

### Redirect

If you add a `redirect` element, then you will explicitly override the global/module setting, and if a match is made, a redirect will occur for the event registered.

```javascript
{
    "secureList" : "*",
    "redirect" : "mysecret.event"
}
```

### OverrideEvent

If you add an `overrideEvent` element, then you will explicitly override the global/module setting, and an event override will occur.

```javascript
{
    "secureList" : "*",
    "overrideEvent" : "main.onInvalidEvent"
}
```

### Action

If you add an `action` element, then you will be explicitly overriding the global/module setting, and the action will be based on this value (`override` or `event` or `block`)

```javascript
{
    "secureList" : "^api.*",
    "action" : "override"
}
```

## More on White Lists

If a rule has a white list, then it means that you can declare what are the **exceptions** to **ALLOW** if the incoming URL/event was matched against the `securedList`. This is a great way to say, hey, secure all but allow the following events:

```javascript
{
    "secureList" : ".*",
    "whitelist : "^login"
}
```

{% hint style="danger" %}
Please note: if a rule has a white list, it only applies to the **current** rule. So if the whitelist matches, it the current rule is skipped, and the process continues to the next rule.
{% endhint %}

Sometimes you want to make sure ALL events are secured, except for the ones specified, such as login events. If you add new functionality to your app it is easy to forget a new rule. To prevent unwanted access you could specify a LAST rule, which matches ALL event but NO permission at all. In that case you have to add a whitelist for all events which should still pass, for example:

```javascript
{
    "secureList" : ".*",
    "whitelist" : "login",
    "permissions" : "nonExistingPermission"
}
```


# Security Annotations

Security annotations are used to secure your handler and/or handler actions

CBSecurity also allows you to secure your events via annotations instead of security rules.  The setting that controls this security feature is called `handlerAnnotationSecurity` , which can be set in the [configuration section.](/getting-started/configuration#annotation-security)

The security module has a tiered approach to annotation security as it will check the handler component first and then the requested action method second.  You can apply different security contexts to each level as you see fit.

{% hint style="warning" %}
Please note that the security rules will be run first, and annotations second.
{% endhint %}

See the diagram below for inspecting security based on annotations:

![Annotation based security](/files/-M8lAzQ_KnAxZ_FFxGRS)

## `Secure` Annotation

The firewall will inspect handlers for a `secured` annotation. This annotation can be added to the entire handler or to an action method, or both. The default value of the `secured` annotation is a Boolean `true`. This means we need a user to be **authenticated** to access the action.

<pre class="language-javascript"><code class="lang-javascript">// Secure the entire handler
component <a data-footnote-ref href="#user-content-fn-1">secured</a>{

	function index(event,rc,prc){}
	function list(event,rc,prc){}

}
// Same as this
component secured=true{
}

// Do NOT secure the handler
component secured=false{
}
// Same as this, no annotation!
component{

	function index(event,rc,prc) secured{
	}

	function list(event,rc,prc) secured="list"{

	}
	
}
</code></pre>

## Authorization Context

You can also give the annotation a value, which can be anything you like: A list of roles, a role, a list of permissions, metadata, JSON, etc. Whatever it is, this is called the **authorization context,** and the user validator must be able to authenticate and **authorize** the context, or an invalid **authorization** will occur.

```javascript
// Secure this handler
component secured="admin,users"{

	function index(event,rc,prc) secured="list"{

	}
	
	function save(event,rc,prc) secured="write"{

	}

}
```

The **secured** value will be passed to the validator for authorization.

## Cascading Security

By having the ability to annotate the handler and also the action, you create a cascading security model where they need to be able to access the handler first, **and only then** will the action be evaluated for access as well.

[^1]: The security annotation


# cbSecurity Model

This object is used to provide you with human, fluent and explicit security authorizations, authentication insight, utility and contexts.

## Explicit Authorizations

The `cbSecurity` model is a specialized service that will allow you to do explicit authorizations in any layer of your ColdBox application.

Sometimes, you will need authorization checks outside of the incoming request rules or the handler annotations. This can be from within interceptors, models, layouts, or views. For this, we have provided the `cbSecurity` model so you can do explicit authorization checks anywhere you like.

## `cbSecurity` Model Retrieval

You can inject our model, or you can use our handy `cbsecure()` mixin (handlers/layouts/views) and then call the appropriate security functions:

```javascript
// Mixin: Handlers/Layouts/Views
cbsecure()

// Injection
property name="cbSecurity" inject="@cbSecurity"
```

{% hint style="danger" %}
All security methods will call the application's configured Authentication Service to retrieve the currently logged-in user. If the user is not logged in, an immediate `NoUserLoggedIn` exception will be thrown by all methods.
{% endhint %}

You can now discover our sections for securing using `cbSecurity`

{% content-ref url="/pages/EkvW0uZCt94XDj2r6EbH" %}
[Authentication Methods](/usage/cbsecurity-model/authentication-methods)
{% endcontent-ref %}

{% content-ref url="/pages/-M3gu0RwxlpLSkOo-idX" %}
[Authorization Contexts](/usage/cbsecurity-model/authorization-contexts)
{% endcontent-ref %}

{% content-ref url="/pages/-M3gtW4YzTEAf6ylUmoc" %}
[Blocking Methods](/usage/cbsecurity-model/secure-blocking-methods)
{% endcontent-ref %}

{% content-ref url="/pages/-M3gu8DR7rp1\_Q9WfJJo" %}
[Securing Views](/usage/cbsecurity-model/securing-views)
{% endcontent-ref %}

{% content-ref url="/pages/eA8bHiGeEkS9nCF1E2sT" %}
[Utility Methods](/usage/cbsecurity-model/utility-methods)
{% endcontent-ref %}

{% content-ref url="/pages/-M3gtoOkN9PPbFvyKLXp" %}
[Verification Methods](/usage/cbsecurity-model/verification-methods)
{% endcontent-ref %}


# Authentication Methods

These methods assist a developer in getting insight into the authentication framework.

You can leverage the CBSecurity model to get insight into some aspects of the authentication process or do authentication via the configured authentication service if needed.

### Configured Services

* `getAuthService()` - Get access to the configured authentication service
* `getUserService()` - Get access to the configured user service

### Authentication Context

* `authenticate( username, password )` - Authenticate a request
* `getUser()` - Get the authenticated user of the current request
* `guest()` - Verify if the users is NOT logged in, but a guest
* `isLoggedIn()` - Verify if the current request has authenticated
* `logout()` - Logout the authenticated user




---

[Next Page](/llms-full.txt/1)

