Skip to content

Commit 8d744ce

Browse files
committed
Merge branch 'development' into master
2 parents e4cffb8 + 48c64a8 commit 8d744ce

File tree

9 files changed

+120
-24
lines changed

9 files changed

+120
-24
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ deploy:
133133
edge: true
134134
file_glob: true
135135
file: $TRAVIS_BUILD_DIR/.artifacts/$MODULE_ID/**/*
136-
release_notes_file: changelog-latest.md
136+
release_notes_file: $TRAVIS_BUILD_DIR/changelog-latest.md
137137
name: v${TRAVIS_TAG}
138138
tag_name: v${TRAVIS_TAG}
139139
overwrite: true

box.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name":"ColdBox Security",
3-
"version":"2.6.0",
3+
"version":"2.7.0",
44
"location":"https://downloads.ortussolutions.com/ortussolutions/coldbox-modules/cbsecurity/@build.version@/[email protected]@.zip",
55
"author":"Ortus Solutions.com <[email protected]>",
66
"slug":"cbsecurity",

changelog.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,23 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
----
9+
10+
## [2.7.0] => 2020-SEP-14
11+
12+
### Added
13+
14+
* Contributed module rules are now pre-pended instead of appended. (@wpdebruin)
15+
16+
17+
### Fixed
18+
19+
* Not loading rules by source file detection due to invalid setting check
20+
* Don't trigger ColdBox's invalid event looping protection. It also auto-senses between ColdBox 6 and 5 (@homestar9)
21+
* 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)
22+
* Update token storages so no token rejection anymore when storage is not enabled. (@wpdebruin)
23+
24+
825
----
926

1027
## [2.6.0] => 2020-JUL-22

interceptors/Security.cfc

Lines changed: 53 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/**
1+
/**
22
* Copyright since 2016 by Ortus Solutions, Corp
33
* www.ortussolutions.com
44
* ---
@@ -12,6 +12,7 @@ component accessors="true" extends="coldbox.system.Interceptor" {
1212
property name="rulesLoader" inject="rulesLoader@cbSecurity";
1313
property name="handlerService" inject="coldbox:handlerService";
1414
property name="cbSecurity" inject="@cbSecurity";
15+
property name="invalidEventHandler" inject="coldbox:setting:invalidEventHandler";
1516

1617
/**
1718
* The reference to the security validator for this interceptor
@@ -27,6 +28,11 @@ component accessors="true" extends="coldbox.system.Interceptor" {
2728
* Configure the security firewall
2829
*/
2930
function configure(){
31+
variables.onInvalidEventHandlerBean = javacast( "null", "" );
32+
if ( len( variables.invalidEventHandler ) ) {
33+
variables.onInvalidEventHandlerBean = handlerService.getHandlerBean( variables.invalidEventHandler );
34+
}
35+
3036
// init the security modules dictionary
3137
variables.securityModules = {};
3238

@@ -45,6 +51,9 @@ component accessors="true" extends="coldbox.system.Interceptor" {
4551

4652
// Load up the validator
4753
registerValidator( getInstance( getProperty( "validator" ) ) );
54+
55+
// Coldbox version 5 (and lower) needs a little extra invalid event handler checking.
56+
variables.enableInvalidHandlerCheck = ( listGetAt( controller.getColdboxSettings().version, 1, "." ) <= 5 );
4857
}
4958

5059
/**
@@ -96,12 +105,14 @@ component accessors="true" extends="coldbox.system.Interceptor" {
96105
// Process Module Rules
97106
arguments.settings.rules = variables.rulesLoader.normalizeRules( arguments.settings.rules, module );
98107

99-
// Append them
100-
arrayAppend(
101-
getProperty( "rules" ),
102-
arguments.settings.rules,
103-
true
104-
);
108+
// prepend them so the don't interfere with MAIN rules
109+
// one by one as I don't see a way to prepend the whole array at once
110+
for ( var i = arguments.settings.rules.len(); i >= 1; i-- ){
111+
arrayPrepend(
112+
getProperty( "rules" ),
113+
arguments.settings.rules[i]
114+
);
115+
}
105116

106117
// Log it
107118
log.info( "+ Registered module (#arguments.module#) with cbSecurity" );
@@ -221,7 +232,27 @@ component accessors="true" extends="coldbox.system.Interceptor" {
221232
required currentEvent
222233
){
223234
// Get handler bean for the current event
224-
var handlerBean = variables.handlerService.getHandlerBean( arguments.event.getCurrentEvent() );
235+
var handlerBean = variables.handlerService.getHandlerBean( arguments.event.getCurrentEvent() );
236+
237+
// Are we running Coldbox 5 or older?
238+
// is an onInvalidHandlerBean configured?
239+
// is the current handlerBean the configured onInvalidEventHandlerBean?
240+
if (
241+
variables.enableInvalidHandlerCheck &&
242+
!isNull( variables.onInvalidEventHandlerBean ) &&
243+
isInvalidEventHandlerBean( handlerBean )
244+
) {
245+
// ColdBox tries to detect invalid event handler loops by keeping
246+
// track of the last invalid event to fire. If that invalid event
247+
// fires twice, it throws a hard exception to prevent infinite loops.
248+
// Unfortunately for us, just attempting to get a handler bean
249+
// starts the invalid event handling. Here, if we got the invalid
250+
// event handler bean back, we reset the `_lastInvalidEvent` so
251+
// ColdBox can handle the invalid event properly.
252+
request._lastInvalidEvent = variables.invalidEventHandler;
253+
return;
254+
}
255+
225256
if ( handlerBean.getHandler() == "" ) {
226257
return;
227258
}
@@ -702,5 +733,19 @@ component accessors="true" extends="coldbox.system.Interceptor" {
702733

703734
return len( CGI.REMOTE_ADDR ) ? CGI.REMOTE_ADDR : "127.0.0.1";
704735
}
736+
737+
/**
738+
* Returns true of the passed handlerBean matches Coldbox's configured invalid event handler.
739+
*
740+
* @handlerBean the current handler bean to check against
741+
*/
742+
private boolean function isInvalidEventHandlerBean( required handlerBean ) {
743+
return (
744+
variables.onInvalidEventHandlerBean.getInvocationPath() == arguments.handlerBean.getInvocationPath() &&
745+
variables.onInvalidEventHandlerBean.getHandler() == arguments.handlerBean.getHandler() &&
746+
variables.onInvalidEventHandlerBean.getMethod() == arguments.handlerBean.getMethod() &&
747+
variables.onInvalidEventHandlerBean.getModule() == arguments.handlerBean.getModule()
748+
);
749+
}
705750

706751
}

models/jwt/JwtService.cfc

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ component accessors="true" singleton {
3939
"iat",
4040
"sub",
4141
"exp",
42-
"scopes"
42+
"scope"
4343
];
4444

4545
// Default JWT Settings
@@ -189,7 +189,7 @@ component accessors="true" singleton {
189189
// The unique identifier of the token
190190
"jti" : hash( timestamp & arguments.user.getId() ),
191191
// Get the user scopes for the JWT token
192-
"scopes" : arguments.user.getJwtScopes()
192+
"scope" : arguments.user.getJwtScopes().toList(" ")
193193
};
194194

195195
// Append user custom claims with override, they take prescedence
@@ -712,7 +712,7 @@ component accessors="true" singleton {
712712
if ( listLen( arguments.permissions ) ) {
713713
// Check if the user has the right permissions?
714714
results.allow = (
715-
tokenHasScopes( arguments.permissions, payload.scopes )
715+
tokenHasScopes( arguments.permissions, payload.scope )
716716
||
717717
variables.cbSecurity
718718
.getAuthService()
@@ -731,6 +731,8 @@ component accessors="true" singleton {
731731

732732
/**
733733
* Verify if the jwt token has the appropriate scopes
734+
* @permission
735+
* @scopes a space delimited string of scopes
734736
*/
735737
private function tokenHasScopes( required permission, required scopes ){
736738
if ( isSimpleValue( arguments.permission ) ) {
@@ -739,7 +741,7 @@ component accessors="true" singleton {
739741

740742
return arguments.permission
741743
.filter( function( item ){
742-
return ( scopes.findNoCase( item ) );
744+
return ( scopes.listfindNoCase( item, " " ) );
743745
} )
744746
.len();
745747
}

models/util/RulesLoader.cfc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,11 +77,11 @@ component accessors="true" singleton {
7777
break;
7878
}
7979
default: {
80-
arguments.settings.rulesFile = arguments.settings.rulesSource;
81-
if ( findNoCase( "json", arguments.settings.rulesSource ) ) {
80+
arguments.settings.rulesFile = arguments.settings.rules;
81+
if ( findNoCase( "json", arguments.settings.rulesFile ) ) {
8282
arguments.settings.rulesSource = "json";
8383
}
84-
if ( findNoCase( "xml", arguments.settings.rulesSource ) ) {
84+
if ( findNoCase( "xml", arguments.settings.rulesFile ) ) {
8585
arguments.settings.rulesSource = "xml";
8686
}
8787
}

test-harness/modules_app/mod1/ModuleConfig.cfc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ component {
3434
"invalidAuthorizationEvent" : "mod1:secure.auth",
3535
// You can define your security rules here or externally via a source
3636
"rules" : [
37-
{ "secureList" : "mod1:home" },
38-
{ "secureList" : "mod1/modOverride", "match" : "url", "action" : "override" }
37+
{ "secureList" : "mod1/modOverride", "match" : "url", "action" : "override" },
38+
{ "secureList" : "mod1:home" }
3939
]
4040
}
4141
};

test-harness/tests/specs/integration/JWTSpec.cfc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ component extends="coldbox.system.testing.BaseTestCase" appMapping="/root" {
156156
// The unique identifier of the token
157157
"jti" : hash( timestamp & userId ),
158158
// Get the user scopes for the JWT token
159-
"scopes" : [],
159+
"scope" : [],
160160
"role" : "admin"
161161
};
162162

test-harness/tests/specs/unit/SecurityTest.cfc

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,14 @@ component extends="coldbox.system.testing.BaseInterceptorTest" interceptor="cbse
1313
// setup properties
1414
setup();
1515
variables.wirebox = new coldbox.system.ioc.Injector();
16-
mockController.$( "getAppHash", hash( "appHash" ) ).$( "getAppRootPath", expandPath( "/root" ) );
17-
security = interceptor;
16+
mockController
17+
.$( "getAppHash", hash( "appHash" ) )
18+
.$( "getAppRootPath", expandPath( "/root" ) )
19+
.$( "getColdboxSettings", {
20+
"version": "6.0.0"
21+
}, false );
22+
security = interceptor;
23+
security.setInvalidEventHandler( '' );
1824
settings = {
1925
// The global invalid authentication event or URI or URL to go if an invalid authentication occurs
2026
"invalidAuthenticationEvent" : "",
@@ -131,7 +137,32 @@ component extends="coldbox.system.testing.BaseInterceptorTest" interceptor="cbse
131137
expect( function(){
132138
security.configure();
133139
} ).toThrow( "Security.ValidatorMethodException" );
134-
} );
140+
} );
141+
142+
it( "does not enable invalid event handler processing on Coldbox versions 6+", function() {
143+
security.setProperties( settings );
144+
security
145+
.$( "getInstance" )
146+
.$args( settings.validator )
147+
.$results( wirebox.getInstance( settings.validator ) );
148+
security.configure();
149+
expect( security.$getProperty( "enableInvalidHandlerCheck" ) ).toBeFalse();
150+
} );
151+
152+
it( "enables invalid event handler processing on Coldbox versions prior to 6", function() {
153+
154+
mockController.$( "getColdboxSettings", {
155+
"version": "5.0.0"
156+
}, false );
157+
158+
security.setProperties( settings );
159+
security
160+
.$( "getInstance" )
161+
.$args( settings.validator )
162+
.$results( wirebox.getInstance( settings.validator ) );
163+
security.configure();
164+
expect( security.$getProperty( "enableInvalidHandlerCheck" ) ).toBeTrue();
165+
} );
135166

136167
describe( "It can load many types of rules", function(){
137168
beforeEach( function(currentSpec){
@@ -173,7 +204,8 @@ component extends="coldbox.system.testing.BaseInterceptorTest" interceptor="cbse
173204

174205
expect( security.getProperty( "rules", [] ) ).toHaveLength( 1 );
175206
} );
176-
} );
207+
} );
208+
177209
} );
178210
}
179211

0 commit comments

Comments
 (0)