Skip to content

Commit

Permalink
fix: Support for Multiple Allowed Origins
Browse files Browse the repository at this point in the history
* Added tests for multiple allowed origins

* Added support  for multiple allowed origins

Allowed origins can be provided as a list. If the current origin is found in that list then it is returned as the allowed origin.

* Added a failure expectation

Expectation added to the "can configure for multiple allowed origins" test.
  • Loading branch information
richardherbert authored May 3, 2022
1 parent 09d37d4 commit 1e10b33
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 11 deletions.
16 changes: 5 additions & 11 deletions interceptors/CORS.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,7 @@ component {
return;
}

var allowedOrigins = settings.allowOrigins;
if ( isClosure( allowedOrigins ) || isCustomFunction( allowedOrigins ) ) {
allowedOrigins = allowedOrigins( event );
}
if ( ! isSimpleValue( allowedOrigins ) ) {
allowedOrigins = arrayToList( allowedOrigins, ", " );
}
var allowedOrigin = event.getHTTPHeader( "Origin", "" );

if ( isCachedEvent( event ) ) {
if ( event.getHTTPMethod() != "OPTIONS" ) {
Expand All @@ -53,8 +47,8 @@ component {
var templateCache = getController().getCache( "template" );
var cachedEvent = templateCache.get( event.getEventCacheableEntry().cacheKey );

log.debug( "Setting the 'Access-Control-Allow-Origin' header to #allowedOrigins# for the cached event." );
cachedEvent.responseHeaders[ "Access-Control-Allow-Origin" ] = allowedOrigins;
log.debug( "Setting the 'Access-Control-Allow-Origin' header to #allowedOrigin# for the cached event." );
cachedEvent.responseHeaders[ "Access-Control-Allow-Origin" ] = allowedOrigin;

log.debug( "Setting the 'Access-Control-Allow-Credentials' header to #toString( settings.allowCredentials )# for the cached event." );
cachedEvent.responseHeaders[ "Access-Control-Allow-Credentials" ] = toString( settings.allowCredentials );
Expand All @@ -68,8 +62,8 @@ component {
templateCache.clear( cacheKey );
}

log.debug( "Setting the 'Access-Control-Allow-Origin' header to #allowedOrigins#." );
event.setHTTPHeader( name = "Access-Control-Allow-Origin", value = allowedOrigins );
log.debug( "Setting the 'Access-Control-Allow-Origin' header to #allowedOrigin#." );
event.setHTTPHeader( name = "Access-Control-Allow-Origin", value = allowedOrigin );
log.debug( "Setting the 'Access-Control-Allow-Credentials' header to #toString( settings.allowCredentials )#." );
event.setHTTPHeader( name = "Access-Control-Allow-Credentials", value = toString( settings.allowCredentials ) );

Expand Down
8 changes: 8 additions & 0 deletions tests/resources/app/config/Coldbox.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,14 @@
};
break;

case "multiple_origin_string":
moduleSettings = {
"cors" = {
"allowOrigins" = "example.net,example.com"
}
};
break;

case "allow_methods_array":
moduleSettings = {
"cors" = {
Expand Down
36 changes: 36 additions & 0 deletions tests/specs/integration/CORSSpec.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,42 @@ component extends="tests.resources.ModuleIntegrationSpec" appMapping="/app" {
expect( responseHeadersTwo ).notToHaveKey( "Access-Control-Allow-Origin" );
} );

it( "can configure for multiple allowed origins", function() {
hyper.get( "/", {
"fwreinit": "true",
// testcase configures the module as needed for the test
"testcase": "multiple_origin_string"
} );

var resOne = hyper.setMethod( "OPTIONS" )
.withHeaders( {
"Origin": "example.com",
"Access-Control-Request-Method": "GET",
"Access-Control-Request-Headers": "Content-Type, X-Auth-Token, Origin, Authorization"
} )
.setUrl( "/" )
.send();

var responseHeadersOne = resOne.getHeaders();

expect( responseHeadersOne ).toHaveKey( "Access-Control-Allow-Origin" );
expect( responseHeadersOne[ "Access-Control-Allow-Origin" ] ).toBe( "example.com" );

var resTwo = hyper.setMethod( "OPTIONS" )
.withHeaders( {
"Origin": "exampleTwo.com",
"Access-Control-Request-Method": "GET",
"Access-Control-Request-Headers": "Content-Type, X-Auth-Token, Origin, Authorization"
} )
.setUrl( "/" )
.send();

var responseHeadersTwo = resTwo.getHeaders();

expect( resTwo.getStatusCode() ).toBe( 403 );
expect( responseHeadersTwo ).notToHaveKey( "Access-Control-Allow-Origin" );
} );

it( "can accept a function for the allowed origins", function() {
hyper.get( "/?fwreinit=true" );

Expand Down

0 comments on commit 1e10b33

Please sign in to comment.