Skip to content

Instantly share code, notes, and snippets.

@bennadel
Created December 31, 2013 14:54
Show Gist options
  • Save bennadel/8197963 to your computer and use it in GitHub Desktop.
Save bennadel/8197963 to your computer and use it in GitHub Desktop.
Preventing Cross-Site Request Forgery (CSRF / XSRF) With AngularJS And ColdFusion
<cfscript>
// Set up the default API response.
apiResponse = {
"statusCode" = 200,
"statusText" = "OK",
"contentType" = "application/x-json",
"data" = {}
};
// When processing the API request, we are going to check to see
// if the XSRF cookie and header values match. If either of these
// values is missing, or they do not match, we'll raise an
// exception. This error-oriented routing simplifies the logic.
try {
// The value WE set.
xsrfCookie = cookie[ "XSRF-TOKEN" ];
// The value ANGULARJS set.
xsrfToken = getHttpRequestData().headers[ "X-XSRF-TOKEN" ];
if ( xsrfCookie != xsrfToken ) {
throw( type = "XsrfTokenMismatch" );
}
apiResponse.data[ "method" ] = cgi.request_method;
apiResponse.data[ "time" ] = getTickCount();
} catch ( any error ) {
// If we made it this far, some part of the XSRF validation
// failed. Either one of the tokens was missing; or, the two
// tokens did not match. In any case, the request is not valid.
apiResponse.statusCode = 401;
apiResponse.statusText = "Unauthorized";
apiResponse.data = {};
}
</cfscript>
<cfheader
statuscode="#apiResponse.statusCode#"
statustext="#apiResponse.statusText#"
/>
<!--- Serialize the API response. --->
<cfcontent
type="#apiResponse.contentType#; charset=utf-8"
variable="#charsetDecode( serializeJson( apiResponse.data ), 'utf-8' )#"
/>
<cfscript>
// Set the XSRF token cookie. The cookie is user-specific and
// "salted". Once in place, AngularJS will look for this cookie
// before initiating the $http / $resource requests; when found,
// AngularJS will automatically echo the token in the HEADER
// value, "X-XSRF-TOKEN".
cookie[ "XSRF-TOKEN" ] = lcase(
hash( "#session.cfid#-#session.cftoken#-#getTickCount()#" )
);
</cfscript>
<!--- ----------------------------------------------------- --->
<!--- ----------------------------------------------------- --->
<cfcontent type="text/html; charset=utf-8" />
<!doctype html>
<html ng-app="demo">
<head>
<meta charset="utf-8" />
<title>
Preventing Cross-Site Request Forgery With AngularJS And ColdFusion
</title>
<style type="text/css">
a[ ng-click ] {
color: blue ;
cursor: pointer ;
text-decoration: underline ;
}
</style>
</head>
<body ng-controller="DemoController">
<h1>
Preventing Cross-Site Request Forgery With AngularJS And ColdFusion
</h1>
<p>
<a ng-click="makeGetRequest()">Make GET Request</a>
&mdash;
<a ng-click="makePostRequest()">Make POST Request</a>
&mdash;
<a href="delete_cookie.cfm" target="_blank">Delete XSRF Cookie</a>
</p>
<h3>
API Log
</h3>
<ul>
<li ng-repeat="item in apiLog">
{{ item.message }}
</li>
</ul>
<script type="text/javascript" src="./assets/angularjs/angular.min.js"></script>
<script type="text/javascript" src="./assets/angularjs/angular-resource.min.js"></script>
<script type="text/javascript">
// Define our AngularJS application.
var app = angular.module( "demo", [ "ngResource" ] );
// -------------------------------------------------- //
// -------------------------------------------------- //
// I am the application controller.
app.controller(
"DemoController",
function( $scope, $resource ) {
// I keep track of the API request values.
$scope.apiLog = [];
// I create a proxy for the server-side API end-point.
// I sit on top of the $http resource and will append
// an "X-XSRF-TOKEN" header to all outgoing requests
// if the "XSRF-TOKEN" cookie value is available.
var resource = $resource(
"api.cfm",
{},
{
performGet: {
method: "GET"
},
performPost: {
method: "POST"
}
}
);
// ---
// PUBLIC METHODS.
// ---
// I make GET requests to the API.
$scope.makeGetRequest = function() {
resource.performGet()
.$promise
.then( handleResolution, handleRejection )
;
};
// I make POST requests to the API.
$scope.makePostRequest = function() {
resource.performPost()
.$promise
.then( handleResolution, handleRejection )
;
};
// ---
// PRIVATE METHODS.
// ---
// I handle successful resource resolutions.
function handleResolution( response ) {
$scope.apiLog.unshift({
message: ( response.method + ": " + response.time )
});
}
// I handle resource response rejections.
function handleRejection( response ) {
$scope.apiLog.unshift({
message: "*** XSRF Attack! ***"
});
}
}
);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment