Cross-Site Request Forgery
Every storefront contains some protected requests that require a high level of security protection. Authenticated shoppers who change their accounts or submit personal data to a server to complete an action typically perform these requests. Users expect that they alone make these requests, and only when they specifically initiate the request.
Cross-site request forgery (CSRF) breaks that expectation by tricking the userβs browser into making this protected request without their knowledge, but with their authorization. Salesforce B2C Commerce has a CSRF protection software library so developers can protect requests against this attack.
The CSRF protection API uses a Synchronizer Token pattern that requires random challenge tokens that are associated with the user's current session. When the user submits content from the page, the server is configured to look for and validate that token. If the token fails to validate, the request is rejected.
For sensitive business functions, including a required security token in HTTP requests can help mitigate CSRF attacks. The reason is that to be successful, the attacker has to know the randomly generated token for a particular session.
The API is exposed via the dw.web.CSRFProtection
, which contains the following methods.
-
getTokenName()
: Returns the expected parameter name as a string that maps to a CSRF Token. -
generateToken()
: Securely generates a token string for the current user. Tokens are unique per call to generateToken. -
validateRequest()
: Examines a userβs current request to determine if the request contains a valid CSRF token. A token is valid if it was generated for this userβs session in the last 60 minutes.
Here is an example of a form within ISML that uses the CSRF framework to insert the token parameter name and its corresponding value.
<form action="/submit" method="post">
...
<input name="${dw.web.CSRFProtection.getTokenName()}" value="${dw.web.CSRFProtection.generateToken()">
</form>
Then, call CSRFProtection.validateRequest()
directly in the body of the function or use a middleware implementation to validate the
CSRF token.
A best practice for CSRF in SiteGenesis JavaScript controllers is to include
CSRFProtection.validateRequest()
when handling a specific form
action. It's action-specific because not all actions submit data and require CSRF
protection.
Here's an example of using the method directly in a SiteGenesis JavaScript controller.
formResult = cartForm.handleAction({
//Add a coupon if a coupon was entered correctly and is active.
'addCoupon': function (formgroup) {
var CSRFProtection = require('dw/web/CSRFProtection');
if (!CSRFProtection.validateRequest()) { //validate the request
app.getModel('Customer').logout(); //log the customer out
app.getView().render('csrf/csrf-failed'); //render an error template
return null;
}
var status;
var result = {
cart: cart,
EnableCheckout: true,
dontRedirect: true
};
SFRA comes with a middleware version of CSRF that performs CSRF checks as a middleware step, with a number of supporting methods, including the following.
-
csrfProtection.validateAjaxRequest
to validate the CSRF token on an AJAX request -
csrfProtection.validateRequest
to validate the CSRF token on a non-AJAX request -
csrfProtection.generateToken
to generate a CSRF token to be used in a form and later validated using one of the aforementioned methods
Here's an example of using the middleware.
server.post(
'Login',
server.middleware.https,
csrfProtection.validateAjaxRequest,
function (req, res, next) {
var data = res.getViewData();
if (data && data.csrfError) {
res.json();
return next();
}
);
CSRF in Business Manager
When creating cartridges for Business Manager, B2C Commerce automatically
appends CSRF tokens to every request regardless of the HTTP method. As a result,
validate only the CSRF token name and value using
CSRFProtection.validateRequest()
directly in the body of the
function in Business Manager cartridge controllers.
All first-party Business Manager pages and requests are protected by default with CSRF tokens.