Blog

cbSecurity 2.3 Released

Luis Majano March 30, 2020

Spread the word

Luis Majano

March 30, 2020

Spread the word


Share your thoughts

We are excited to bring you another release for cbSecurity packed with security goodness: version 2.3.0. This version focuses on security contexts from ANY layer of a ColdBox application. It will also enhance your functional skills as well, as it introduces some nice semantics for securing your code.

# Install
install cbsecurity

# Update
update cbsecurity

What's New With 2.3.0

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:

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

// Injection
property name="cbSecurity" inject="@cbSecurity"
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.

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).

// 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:

// 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:

when( permissions, success, fail )
  • The permissions is a permission array or list that will be Or'ed
  • The success is a closure/lambda or UDF that will execute if the permissions validate.
  • 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.

// 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:

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:

// 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.

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!
// 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


    This is only visible to user admins!



    Impersonate User



    This is You!

Other Layers:

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

if( cbSecurity.sameUser( prc.incomingUser ) ){
    // you can change your gravatar
}
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.

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:

secureWhen( context, [errorMessage] )

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

// 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.

( 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.

cbSecurity injects the `secureView()` method into the request context via the `preProcess` interception point.
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 )

Add Your Comment

Recent Entries

BoxLang v1.8.0 : Revolutionary HTTP Client, SOAP Integration, and Production-Grade Stability

BoxLang v1.8.0 : Revolutionary HTTP Client, SOAP Integration, and Production-Grade Stability

The BoxLang team is excited to announce BoxLang 1.8.0, a massive release that revolutionizes HTTP capabilities, introduces comprehensive SOAP/WSDL integration, and delivers over 100 critical bug fixes for production-grade stability. This release focuses on modern web application development with fluent APIs, streaming support, persistent connection management, and extensive CFML compatibility improvements.

Luis Majano
Luis Majano
December 05, 2025
Ortus & BoxLang November Recap 2025

Ortus & BoxLang November Recap 2025

November 2025 was a big month at Ortus. BoxLang 1.7.0 arrived with real-time streaming, distributed caching, and faster compiler internals. ColdBox gained a cleaner debugging experience with full Whoops support, while CBWIRE 5 launched with stronger security, smarter lifecycles, and easier uploads.

Victor Campos
Victor Campos
December 02, 2025
Thanksgiving Week Extended + Cyber Monday Deals Are Live!

Thanksgiving Week Extended + Cyber Monday Deals Are Live!

Because you asked; we’re extending the Thanksgiving Week offer and officially launching our Cyber Monday BoxLang Deals today!

To support everyone who wants to understand whether they’re running on legacy CFML or modern-ready code, and whether BoxLang is the right fit; we’ve decided to extend the dates and increase the number of companies we can support.

Maria Jose Herrera
Maria Jose Herrera
December 01, 2025