I developed the RememberMe Forgebox module to give developers a simple API for “remembering” users across sessions and automatically logging them in using their favorite auth library, like cbAuth. I would like for the RememberMe module to also play nicely with cbSecurity.
My recommended implementation of RememberMe, was to use the preProcess()
interceptor method to check if the user is logged in, and if not, recall them, like this:
function preProcess( event, interceptData, buffer, rc, prc ) {
// if the user is not logged in, and the rememberMe cookie exists, attempt to recall the user
if (
!auth().isLoggedIn() && // <-- cbAuth method
remember().cookieExists()
) {
try {
// attempt to recall the user
// if successful, returns a user object from your `userServiceClass`
var user = remember().recallMe();
// verify the user exists and log them in using cbauth
if ( user.isLoaded() ) {
auth().login( user ); // <-- cbAuth method
}
// if the token is invalid, forget the user and cleanup bad cookies
} catch( InvalidToken e ) {
remember().forgetMe();
}
}
Unfortunately, under certain circumstances, cbSecurity’s preProcess()
interceptor method fires before RememberMe, so the firewall check occurs before reauthenticating the user. D’oh!
To the best of my knowledge, I cannot control the order in which the preProcess()
interceptor calls fire. So, in lieu of a prePreProcess()
interception point, what would be a good way to ensure an app has a change to recall a user before cbSecurity can perform the firewall check?
What about SessionStart()?
My initial thought was to use the sessionStart()
interception point. However, I ran into instances where RememberMe’s or CBAuth’s global UDF helpers weren’t registered by the time sessionStart()
fired and it triggered exceptions. I also ran into race conditions when using the provider:
injection annotation, so I’m fairly sure I need to use an interception method that occurs after sessionStart()
and before preProcess()
Perhaps if cbSecurity had a preFirewall()
interceptor, I could update RememberMe’s documentation to use that interception point instead of preProcess()
?
That change would look something like this:
// modules\cbsecurity\interceptors\Security.cfc
/**
* Our firewall kicks in at preProcess
*
* @event
* @interceptData
* @rc
* @prc
* @buffer
*/
function preProcess( event, interceptData, rc, prc, buffer ){
// Add SecureView() into the requestcontext
arguments.event.secureView = variables.cbSecurity.secureViewProxy;
// announce the firewall check
interceptorService.announce( "cbSecurity_preFirewall" );
// Execute Rule Security
...
// Execute Annotation Security
...
I know performance is paramount with cbSecurity, so I’m reluctant to suggest adding new calls that would fire on every request.
Additionally, if there’s a way to delay firing the sessionStart()
interceptor until I can use the provider:
injection DSL, that could be another way to go.
If anyone has any ideas, I’d love to hear them!