Skip to content
Merged

Bump #17

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions ModuleConfig.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ component {
// 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,
// The interval in seconds within which, if a token's expiration is impending, we force generate new token for the user.
timeoutSkew : 60,
// Enable the /cbcsrf/generate endpoint to generate cbcsrf tokens for secured users.
enableEndpoint : false,
// The WireBox mapping to use for the CacheStorage
Expand Down
16 changes: 8 additions & 8 deletions box.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name":"ColdBox Cross Site Request Forgery (CSRF)",
"version":"3.2.0",
"version":"3.3.0",
"location":"https://downloads.ortussolutions.com/ortussolutions/coldbox-modules/cbcsrf/@build.version@/cbcsrf-@build.version@.zip",
"author":"Ortus Solutions.com <info@ortussolutions.com>",
"slug":"cbcsrf",
Expand All @@ -27,7 +27,7 @@
"cbstorages":"^3.0.0"
},
"devDependencies":{
"commandbox-boxlang":"*",
"commandbox-boxlang":"*",
"commandbox-cfformat":"*",
"commandbox-docbox":"*"
},
Expand All @@ -47,11 +47,11 @@
"format:watch":"cfformat watch handlers/,interceptors/,models/,test-harness/tests/specs,ModuleConfig.cfc ./.cfformat.json",
"format:check":"cfformat check handlers/,interceptors/,models/,test-harness/tests/specs,ModuleConfig.cfc",
"install:dependencies":"install && cd test-harness && install",
"start:lucee" : "server start serverConfigFile=server-lucee@5.json",
"start:2021" : "server start serverConfigFile=server-adobe@2021.json",
"stop:lucee" : "server stop serverConfigFile=server-lucee@5.json",
"stop:2021" : "server stop serverConfigFile=server-adobe@2021.json",
"logs:lucee" : "server log serverConfigFile=server-lucee@5.json --follow",
"logs:2021" : "server log serverConfigFile=server-adobe@2021.json --follow"
"start:lucee":"server start serverConfigFile=server-lucee@5.json",
"start:2021":"server start serverConfigFile=server-adobe@2021.json",
"stop:lucee":"server stop serverConfigFile=server-lucee@5.json",
"stop:2021":"server stop serverConfigFile=server-adobe@2021.json",
"logs:lucee":"server log serverConfigFile=server-lucee@5.json --follow",
"logs:2021":"server log serverConfigFile=server-adobe@2021.json --follow"
}
}
7 changes: 7 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Fixed

- Marked `CBCsrf` as `threadSafe` so WireBox publishes the singleton only after
autowiring it. Concurrent requests hitting a cold singleton cache (right after a
framework reinit, for instance) could otherwise get a half-wired instance and fail
with `variable [CACHESTORAGE] doesn't exist`.

## [3.2.0] - 2025-02-19

### Added
Expand Down
26 changes: 19 additions & 7 deletions models/cbcsrf.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* ---
* Service that encapsulates token security against cross site request forgery (csrf)
*/
component accessors="true" singleton {
component accessors="true" singleton threadSafe {

/* *********************************************************************
** DI
Expand Down Expand Up @@ -60,12 +60,7 @@ component accessors="true" singleton {
// Is it a new key?
!csrfData.keyExists( arguments.key ) ||
// Has the token expired?
(
csrfData[ arguments.key ].expires != "never" && dateCompare(
now(),
csrfData[ arguments.key ].expires
) == 1
)
tokenInExpiryRange( csrfData[ arguments.key ] )
) {
// Generate a new token
csrfData[ arguments.key ] = {
Expand All @@ -87,6 +82,23 @@ component accessors="true" singleton {
return csrfData[ arguments.key ].token;
}


/**
* Determines if the token is within the expiry range
*
* @tokenData The token data struct
*
* @return True if the token is within the expiry range
*/
private boolean function tokenInExpiryRange( required struct tokenData ){
if ( tokenData.expires == "never" ) {
return false;
}

var secondsToExpiry = dateDiff( "s", now(), tokenData.expires );
return secondsToExpiry <= variables.settings.timeoutSkew;
}

/**
* Validates the given token against the same stored in the session for a specific key.
*
Expand Down
2 changes: 2 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ moduleSettings = {
// 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,
// The interval in seconds within which, if a token's expiration is impending, we force generate new token for the user.
timeoutSkew : 120,
// Enable the /cbcsrf/generate endpoint to generate cbcsrf tokens for secured users.
enableEndpoint : false,
// The WireBox mapping to use for the CacheStorage
Expand Down
Loading