Exploitation of access control vulnerabilities is a core skill of attackers. To protect against the attackers, enforce server-side access control checks for business functions such as account management, order management, and purchasing.
To control access to sensitive objects, use authentication and authorization. The following objects are examples of sensitive objects:
- Order
- Customer
- CustomerPaymentInstrument
- OrderPaymentInstrument
- Basket
B2C Commerce identifies Script API objects using object identifiers (universally unique identifier (UUID), ID, Token). Knowing the identifiers shouldn’t grant read or write access to sensitive objects. Always perform additional authentication and authorization in the storefront before processing any requests. Some script APIs provide both secure and insecure methods. Although insecure methods accommodate legacy use cases, we highly recommend using the secure methods.
For example, the class OrderMgr provides two signatures to the method getOrder:
static getOrder(orderNumber : String)
static getOrder(orderNumber : String, orderToken : String)
The second signature is the secure method. For more information, see Class OrderMgr.
The second signature is the secure method. For more information, see Class OrderMgr.
Authentication
If you use the Storefront Reference Architecture (SFRA) in your cartridge path, you
can use its userLoggedIn middleware capability to check whether
the request is from an authenticated user. This middleware exposes the
validateLoggedIn function to check whether the user is
authenticated to invoke the function. The middleware also exposes the
validateLoggedInAjax function to validate whether a user is
authenticated from an AJAX request.
var userLoggedIn = require('*/cartridge/scripts/middleware/userLoggedIn');
server.get(
'Show',
server.middleware.https,
userLoggedIn.validateLoggedIn,
consentTracking.consent,
function (req, res, next) {
var CustomerMgr = require('dw/customer/CustomerMgr');
var Resource = require('dw/web/Resource');
var URLUtils = require('dw/web/URLUtils');
This code snippet includes the middleware userLoggedIn for an
exposed business function.
If you use SiteGenesis in your cartridge path, you can use guards to wrap controller functions when they’re exported. The functions specified in the guard module act as a request filter. You can specify multiple levels of access to controller functionality.
- Require HTTPS.
- Require or forbid a certain HTTP method, like GET or POST.
- Require that a current user is logged in.
This example shows an edit profile controller that requires HTTPS and that the user is logged in.
exports.EditProfile = guard.ensure(['get', 'https', 'loggedIn'], editProfile);
Authorization
When implementing storefront operations, use authorization checks that are relevant to your business workflow. When performing an administrative action on a sensitive object, authenticate the requesting user using a secret about that object. For example, when a guest creates an account after successfully checking out, and B2C Commerce reassigns the order to that guest, authenticate the user using a secret about the order. This approach provides high confidence that the requesting user is the user who created the object.
The following sections include examples of authorization checks for the Order object for registered and guest shoppers.
Registered Shoppers
When a registered shopper wants to access an order, verify the following information in the storefront:
- The shopper is authenticated. Enforce a server-side authenticated-user check,
such as the SFRA
userLoggedInmiddleware or SiteGenesis guards. - The order has a cancelable status. Whether a status is cancelable depends on the order management flow of each storefront. See Class Order for supported statuses.
- The order has a cancelable status. Whether a status is cancelable depends on the order management flow of each storefront. See Class Order for supported statuses.
- The shopper owns the order to cancel.
var orderCustomer = order.getCustomer();
var sessionCustomer = session.getCustomer();
If ( orderCustomer.ID === sessionCustomer.ID ) {
// The logged-in shopper is the owner of the order
// perform actions in accordance with the order management workflow
...
} else {
// A user attempts to access an order they don’t own
// Reject this request with an error message ( HTTP 401 unauthorized or a custom error page)
// Log an error message to track this occurrence
}
Guest Shoppers
Implementing a robust authentication and authorization scheme that applies to guest (unregistered) shoppers is more challenging than for registered shoppers. To reduce the risk of fraud, consider the following options as applicable for your use case:
- Prohibit guest shoppers from changing existing orders; prompt them to create an account when they try to change orders.
- Allow access to an order only if the shopper can produce the order number,
order token, and a combination of other data included in the order, such as:
- Last name
- Postal code
- Phone number
- Don’t allow guest shoppers to access orders that registered users own.
- Limit the permitted actions to the strict minimum. For example:
- Don’t display payment or personal information stored in the order.
- Don’t allow changes that let a malicious user modify the order, for example, changing the shipping address.
- Implement bot/script protection controls to protect from brute force attacks.
For example:
- Rate limiting
- Completely Automated Public Turing test to tell Computers and Humans Apart (CAPTCHA)