CX Works

CX Works brings the most relevant leading practices to you.
It is a single portal of curated, field-tested and SAP-verified expertise for SAP Customer Experience solutions

Data Protection in SAP Commerce Cloud

21 min read

Data Protection in SAP Commerce Cloud

In most cases, compliance with data privacy laws is not a product feature. However, SAP software supports data privacy, by providing security features and specific data-protection-relevant functions such as, simplified blocking and personal data deletion.

SAP does not provide legal advice in any form. The legal definitions and terms used in this guide are not from a legal source.

Your data protection requirements should outline what is necessary for your solution to be compliant with the requirements of the regions you operate in. This section covers potential data protection topics and how you to implement them.

Table of Contents

Consent Management

Tracking

When you're tracking a customer’s data on your solution, using cookies, order entries, or other methods, make sure your customer understands their data is being tracked. This requirement applies to registered and anonymous users. If your customer does not consent to tracking, make sure your solution respects their request.

Further, your solution needs to account for merges between anonymous consent tracking and a registered user. With SAP Commerce 6.6 the ability to track anonymous users and then associate them to their registered account is covered in help.hybris.com.

Requesting Consent

Consent for retaining personal data needs to be an option for customer to agree to whenever data will be collected. These consent entry points , where consent can be provided, should be implemented in the appropriate sections of your solution. Additionally you could use SAP Customer Consent (part of Customer Data Cloud) to simplify the process. For example:

  1. The first time the data is to be collected (typically as part of the registration process).
  2. Whenever the customer decides they wish to have their personal data collected. This can either be done on a case by case basis where you may feel it is appropriate to advertise how collection of data may benefit the customer, or through something like their Account Management settings.

If you have multiple baseStores, it is important to realize that you can potentially have different consent types for each store and ensure your data model is set up to correctly achieve this.

As part of SAP Commerce 6.6, the consent request templates have been incorporated into the registration page as well as part of "My Account". The consent template examples are a part of the storefront code in the b2c_acc recipe. Further, new templates can be created, modified, or removed. For more details on how to adjust the templates please visit the Consent Template page.

Removing Consent/Data Retention

Your customer has the right to remove consent at any moment, which means:

  1. You have to provide a mechanism to display what they’ve consented to.
  2. You must provide an option to remove what they’ve consented to.
  3. You must respect laws around data retention; make sure your customer’s data is removed from your system, after its retention period. See Personal Data Erasure for how this is implemented in SAP Commerce 6.6.


Retention periods vary, depending on the type of data (tickets, orders, addresses and others). Make sure you have the retention periods documented, as part of your business requirements.


When a customer revokes their consent to have their information tracked or wants to close their account, the information should be deleted. Also, data that has past a retention period should be deleted Example cronjobs  are provided in SAP Commerce 6.6 to remove order, tickets, customers, and personal data reports, after a retention period has passed. If you don’t have this version, place an attribute that tracks consent changes and add cronjobs, which remove expired data that has passed the retention period. For older versions of SAP Commerce, you can  potentially leverage the Dynamic Maintenance Job to remove the relevant data

If you're using Data Hub, review how long the data is retained in the pool. In SAP Commerce 6.6 you can specify the retention period for a pool and have it permanently.

Data Anonymization

Most SAP Commerce solutions require integration with at least one 3rd party service. This means that personally identifiable information (PII) can be sent outside your network. One practice to secure PII is to anonymize it, by stripping the PII and replacing it with a hash. A second option is to anonymize or encrpyt the entire data, so that it can only be decrypted by the 3rd party, with the correct key. That way, if the data is intercepted it will not contain the PII or the data will be hard to decrypt.

SAP Commerce Cloud does provide the option to anonymize your snapshots as covered in Strategies for Loading Data in SAP Commerce Cloud. If you are looking to secure individual fields you can use Transparent Attribute Encryption to encrypt the data for specific item types.

In cases where you are taking a dump of your database and either loading into lower environments or sharing outside of your Commerce Cloud solution (e.g. for statistical analysis). This data must be protected to ensure privacy or protect confidential company data (e.g. industry benchmarking). Numerous laws in different countries restrict the processing of personal data, especially of sensitive personal data. However, if the data is anonymized, these restrictions don’t apply anymore, meaning that the data can be processed and analyzed as required. Below we cover a couple of options to anoymize a data set to be used outside of production.

Step-by-Step

  1. Identify the personal identifiable information - Decide which sensitive attributes need to be protected, and identify where they are stored on your application.
  2. Write anonymization scripts (see below) - Create a script that will run through your dataset and obfuscate all the PII. 
  3. Execute scripts - Run the script to anonymize, depending on the volume of data, this step may take some time to execute.
  4. Validate - Run queries or check on the backoffice to make sure that the data has been properly anonymized.

Sample Anonymization Scripts

This article provides 2 template scripts to anonymize databases as a reference. They will have to be adapted to include custom parameters for your implementation, but they provide a good starting point to build upon.

The following scripts serve as starting point for your anonymization efforts. It's your responsibility to extend them to cover all required fields. They should never be run against your production database.

Option #1 Direct SQL

This script is a set of SQL Updates that can be executed from the hybris Admin Console via the Direct SQL section. This script is fast, since it skips the Service Layer, so no Interceptors are triggered.

SQL Script
# Example of SQL queries to update sensitive attributes 
# by concatenating a random token to a random numbers: fake-uid + ABS(RAND() ...)
# Or by replacing it with a random value of a choice: 'redacted'

UPDATE users SET uniqueid=CONCAT("fake-uid",  ABS(RAND() * 10000000000), ABS(RAND()*100)) WHERE TypePKString = "8796094267474" AND uniqueid NOT IN ('admin', 'anonymous', 'kiev', 'autotestuser');

UPDATE users SET passwd=null WHERE TypePKString = "8796094267474" AND uniqueid NOT IN ('admin', 'anonymous', 'kiev', 'autotestuser');

UPDATE users SET name='Firstname Lastname' WHERE TypePKString = "8796094267474" AND uniqueid NOT IN ('admin', 'anonymous', 'kiev', 'autotestuser');

UPDATE users SET p_originaluid=CONCAT("fake-ouid", ABS(RAND() * 10000000000), ABS(RAND()*100)) WHERE TypePKString = "8796094267474" AND uniqueid NOT IN ('admin', 'anonymous', 'kiev', 'autotestuser');

UPDATE users SET p_customerid=CONCAT("fake-cid",  ABS(RAND() * 10000000000), ABS(RAND()*100),'.com_e5p-uk') WHERE TypePKString = "8796094267474" AND uniqueid NOT IN ('admin', 'anonymous', 'kiev', 'autotestuser');


UPDATE addresses SET p_email=CONCAT("email",  ABS(RAND()* 10000000000), ABS(RAND()*100), "@domain.com.noresolve");
UPDATE addresses SET p_firstname='Firstname';
UPDATE addresses SET p_lastname='Lastname';
UPDATE addresses SET p_streetnumber='line 1';
UPDATE addresses SET p_streetname='line 2';
UPDATE addresses SET p_postalcode='XX1 0XX';
UPDATE addresses SET p_town='London';
UPDATE addresses SET p_phone1='00000000000';
UPDATE addresses SET p_phone2='00000000000';
  
UPDATE paymentinfos SET p_type=null ;
UPDATE paymentinfos SET p_validtoyear='redacted';
UPDATE paymentinfos SET code=CONCAT("fake-c", ABS(RAND() * 10000000000), ABS(RAND()*100));
UPDATE paymentinfos SET p_bank='redacted';
UPDATE paymentinfos SET p_ccowner='redacted';
UPDATE paymentinfos SET p_number=CONCAT("fake-n", ABS(RAND() * 10000000000), ABS(RAND()*100));
UPDATE paymentinfos SET p_accountnumber='redacted';
UPDATE paymentinfos SET p_validtomonth='redacted';


UPDATE paymenttransactions SET p_requesttoken=CONCAT("fake-pt-rtoken", ABS(RAND() * 10000000000), ABS(RAND()*100));

UPDATE paymnttrnsctentries SET p_requesttoken=CONCAT("fake-pte-rtoken", ABS(RAND() * 10000000000), ABS(RAND()*100));
UPDATE paymnttrnsctentries SET p_code=CONCAT("fake-code", ABS(RAND() * 10000000000), ABS(RAND()*100));
UPDATE paymnttrnsctentries SET p_transactiondetails='redacted';

UPDATE paypalpaymentinfos SET code=CONCAT("fake-code", ABS(RAND() * 10000000000), ABS(RAND()*100));
UPDATE paypalpaymentinfos SET p_paypalcustomeremail='redacted';
UPDATE paypalpaymentinfos SET p_paypaltoken='redacted';
UPDATE paypalpaymentinfos SET p_paypalpayerid='redacted';

UPDATE paypalpaymenttrans SET p_code=CONCAT("fake-code", ABS(RAND() * 10000000000), ABS(RAND()*100));
UPDATE paypalpaymenttrans SET p_requestid='redacted';
UPDATE paypalpaymenttrans SET p_paypalauthtransactionid='redacted';
UPDATE paypalpaymenttrans SET p_paypalpayerid='redacted';
UPDATE paypalpaymenttrans SET p_paypaltoken='redacted';

UPDATE contactus SET p_telephonenumber='redacted';
UPDATE contactus SET p_email='redacted';
UPDATE contactus SET p_name='redacted';

UPDATE emailaddress SET p_emailaddress='redacted'; 
UPDATE emailaddress SET p_displayname='redacted';

UPDATE discounts SET p_codes='redacted'; 
UPDATE discounts SET p_vouchercode='redacted';

UPDATE socialaccount SET p_socialuserid='redacted'; 
UPDATE socialaccount SET p_name='redacted'; 
UPDATE socialaccount SET p_dataforanalytics ='redacted';


UPDATE users SET p_brontoid ='null';
UPDATE users SET p_token=CONCAT("fake-code", ABS(RAND() * 10000000000), ABS(RAND()*100));


Execute in HAC → Console → FlexibleSearch → SQL Query:


Example before anonymization:

uiqueid passwd name p_originaluid accountnumber phonenumber
user1 p925AOGQWIHH76oCM9plHg username1 8796093055008 43210654 5189671435
user2 maEXWxEj01T2FBsWRQHqSw usernam2 9685082064009 43221789 5180543975


Example after anonymization:

uiqueid passwd name p_originaluid accountnumber phonenumber
fake-uid9.421341e+00983.2563 **** AnonymizedName fake-ouid9.51304e+00929.6798 redacted 0000000000
fake-uid9.650980e+00983.2563 **** AnonymizedName fake-ouid5.6723e+00993.1756 redacted 0000000000


Option #2 - Groovy

Depending on the size of your dataset, the scripts above may take a long time to be executed.

This script is executed from the Groovy console in HAC. This script is slow because it will go through the Service Layer, but it ensures all validations are executed.

Groovy script
# Example of a Groovy Script to update sensitive attributes 
# by concatenating a random token to a random numbers: fake-uid + ABS(RAND() ...)
# Or by replacing it with a random value of a choice: 'redacted'
# It defines functions to run flexible search queries
# Then a loop on each record in the query results to update with random values using modelService.save

import de.hybris.platform.servicelayer.search.FlexibleSearchQuery;
flexibleSearchService = spring.getBean "flexibleSearchService";
modelService = spring.getBean "modelService"
def findCustomers() {
    query    = new FlexibleSearchQuery("select {pk} from {Customer} where {type} is not null and {uid} != 'Anonymous' and {uid}         not like '%@anonymous.com' order by {uid} limit 40000")
    flexibleSearchService.search(query).result
}

final java.util.Date now = new java.util.Date();
final java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyyMMddHHmmss");
final String unique = sdf.format(now);

int ccount = 0;
String atcom = "@anonymous.com";
findCustomers().each {      
        it.uid = "customer" + ccount + "." + unique + atcom
        it.description = "Customer" + ccount
        it.password = "12345"
        ccount += 1;
        modelService.save(it)
        println "anonymizing customer " + ccount
}
def findEmployees() {
    query = new FlexibleSearchQuery("select {pk} from {Employee} where {name} not like 'EmployeeAnonymized%'")
    flexibleSearchService.search(query).result
}
int ecount = 0;
findEmployees().each {
        it.name = "EmployeeAnonymized" + ecount + it.name
        it.password = "12345"
        ecount += 1;
        modelService.save(it)
        println "anonymizing employee " + ecount
}
def findAddresses() {
    query = new FlexibleSearchQuery("select {pk} from {Address} where {email} not like 'forumhybris2@gmail.com' order by {email} limit 40000 ")
    flexibleSearchService.search(query).result
}
int acount = 0;
findAddresses().each {
    it.firstname = "FirstName" + acount
    it.lastname = "LastName" + acount
    it.pobox = "pobox" + acount
    it.postalcode = "pc" + acount
    it.streetname = "streetname" + acount
    it.streetnumber = "streetnumber" + acount
    it.town = "town" + acount
    it.email = "forumhybris2@gmail.com"
    acount += 1;
    modelService.save(it)
    println "anonymizing address " + acount
}


Execute in HAC → Console → Scripting Languages → Edit Statement → Script Type (groovy):



Example before anonymization:

uid description password
original@uid1.com Original Description Value1 d189fc47636b2545f3136ecab286bc3e
original@uid2.com Original Description Value2 26b6bb96b963ddd6c5f1cb9eb997b0e0


Example after anonymization:


Personal Data Reporting

Although audit trails are important, because they help track who is accessing the data, it is important for a customer to understand what type of data is being collected on them. As part of your data protection requirements you need to outline:

  • how many types of reports you need
  • what data should be displayed in the report
  • how the data should be displayed
  • who can generate and access the report

Using the Data Annotation Framework provided in SAP Commerce 6.5 you can define the reports and the data it generates. Once the report has been defined, we recommend you create at least one consent template to make it easy to read for anybody.

By default, the Personal Data Report can be created through the support ticket process. If you need to generate it elsewhere, you can always call:


// Assuming you have UserService injected by Spring
final UserModel user = userService.getUserForUID("sampleUser");
 
// Assuming you have AuditViewService injected by Spring and a audit config named 'sampleConfig'
final Stream<ReportView> report = auditViewService.getViewOn(TypeAuditReportConfig.builder().withConfigName("sampleConfig").withRootTypePk(user.getPk()).build());

Authentication

Authentication is a key aspect of data protection because it verifies the user’s identity. Authentication is not to the same as authorization, which allows the authenticated user to access the system/data they are requesting.

Password Encryption

Passwords are a popular form of authentication. As part of your Account Management requirements you should include the ability for a user to create and change their password. On the backend, these passwords are typically stored and retrieved from the database. Regardless of the password policy you have in place, it is important to consider how the password is stored in your database, especially with the rise of cyber-attacks. We see passwords being stored in plain text, with weak encryption, or being reused. These practices can create issues for multiple solutions

Follow good practice; make sure the passwords you encrypt are hard to decrypt. If you're using a poor form of encryption you should consider Password Encoding Migration.

In addition to passwords, it is important to encrypt sensitive information. Use Transparent Attribute Encryption features within SAP Commerce to better secure your data.

Password Expiration

Having a password is the first step. But, to make your system more secure and to comply with local regulations, you may need to set an expiration date for some or all of your passwords. This feature is not available in a vanilla version of SAP Commerce, but on a high level it requires you to:

  • Add a password and change date attribute to your User type
  • Modify your login to have a filter that checks if the password has expired and redirects the user to a change password page
  • Re-authenticate, once the password is changed

SAP CX Customer Success and Services has implemented this feature for multiple customers. Please email sapcx-services@sap.com if you would like more details.

Two-Factor Authentication (2FA)

Two- factor authentication (2FA) is a type of Multi-factor authentication, where the user is asked for a password and a second factor of authentication, to prove their identity. The first factor for most commerce solutions will utilize a knowledge factors (for example, password + PIN). Those solutions implementing a second factor will usually use a generated token which the user retrieves from a mobile authentication app (like Google Authenticator), via mobile call/text or in some cases a physical token. Although the mobile call/text may be the most popular for a commerce solution, it has some drawbacks, including:

  • it requires the user to have their mobile device available when logging in
  • by using cellular technology it opens up the possibility of man in the middle attacks
  • it may require text/roaming fees in order for the user to get their message

Regardless, having a second factor is more secure than just a single password, but it does introduce added complexity for accessing your solution.

2FA is not available as part of SAP Commerce, but at a high level, if you're writing your own service it would require:

  • Modification to the authentication filter, to add the 2 nd factor step after password validation
  • An implementation of AuthenticationProvider to call your 2FA authentication implementation
  • A method to generate a token
  • A way to store the token
  • A way to send the token to the user (email and/or SMS)
  • A form for the user to enter the token
  • A way to validate the token entered by the user, corresponds to the stored token

SAP CX Customer Success and Services has implemented this functionality for multiple customers. Please email sapcx-services@sap.com if you would like more details.

Integration with an Identity Provider

Another way to authenticate access to your application is to make use of an Identity Provider (IDP). When using the samlsinglesignon extension provides the request flow between the user, an IDP and your application to help achieve single sign-on (SSO). By utilizing an IDP and SAML you can achieve SSO functionality for backofficeassisted service module and C4C. A detailed example of setting up an IDP can be found SAML Single Sign-On Trail.

If you're looking to utilize OAuthfor authentication (typical for webservices) you can investigate whether the Platform as an ID Provider could work for you.

To make your application more accessible and provide a single source to secure and maintain, you can reduce the use of username/passwords and centralize authentication within an identity provider.

Authorization

In some cases, you will have to restrict data access to users of a specific group, to make sure only business users that require access are able to view it. Having an effective User Management setup is critical to authorization working, as visibility is typically done at the user group level. Once you've defined your user groups appropriately you can set the type system permissions.

Audit Logging

Audit logging stores who performed what action (create, read, update, delete) on an item. Although we covered personal data reporting, we haven't discussed the importance of storing personal data or considerations around logging who creates, reads, updates, or deletes the data. Audit logging can help provide critical information during privacy breach investigation because it reveals when data was accessed. With SAP Commerce version 6.6 the Data Annotation Framework introduced in 6.5 was augmented with additional features to define and track changes for particular data types. A default implementation is provided which can be found in Generic Audit. It is up to you to determine what types need to be audited and configure your solution appropriately. 

Depending on how many types you choose to audit and how often they are changing, the size of your database can grow. Ensure you're configuring only those item types that are required and determine if there is a way to archive older audit data

3rd Party Integrations

In your  data protection requirements you need to identify the integrations that will be processing personal data. It is important to secure any communication with these third parties by limiting  the  PII you send and  minimizing the amount of information you store on the system. When you reduce the amount of PII you store in your system, you reduce the impact a potential data breach could have.  The best example of this practice is credit card information. If the 3rd party is storing certain information that you don't need or you can retrieve the information you need from the third party, then you have no reason to store it. If you are retrieving data from a third party then you should make sure it's non-critical or you should have a workaround, in case the data can't be retrieved.

Secure Communication

As much as possible, make sure any traffic in production between a user's browser and your servers is encrypted, which is most often done via SSL. For Commerce Cloud in the Public Cloud this is done for all endpoints, or you can load your own. If you're managing your own infrastructure, for lower environments (dev, test, and others) it may not be necessary, but it should be tested in your staging environment, before the go live. The SAP Commerce solution comes with a certificate signed by a self-signed RootCA as explained in HTTPS Traffic Certificate. It is advised not to use this certificate in production because the key is known.

The table below outlines the SAP Commerce application and the version in which SSL connections were provided as default:

Application Version Encrypted
Storefront 5.5.1
Backoffice 6.2
hAC 6.2
Solr 6.6
Data Hub 6.6

GDPR

While all the details in this article are related to general Data Protection principles, it is important to mention the European Union General Data Protection Regulation (GDPR), which regulates the use of Personal Data by businesses because it may impact your operations.

  • WHAT? – Any information related to a natural person must be protected
  • WHO? – GDPR applies to all companies processing and holding personal data of people residing in the EUregardless of the company’s  location. This means the legislation will have an effect on non EU-based companies IF they have EU-based customers.
  • WHEN? – GDPR came into effect on 25 May 2018 
  • THEN WHAT? – Organizations can be fined up to 4% of annual global turnover for breaching GDPR or €20 Million.

For details around how functionality introduced in SAP Commerce versions can help you with your journey to GDPR compliance, please consult the SAP Commerce Roadmap.


Regardless of what version of SAP Commerce you are on, it will not make you compliant with GDPR. It only offers features and functionality that can be leveraged to be compliant. The Data Controller is accountable for ensuring you are compliant.

Conclusion

Data protection is about protecting your customer's and employees' information. It's your responsibility to secure the data you produce. If you're interested in learning more, we offer a GDPR Assessment for SAP Commerce Cloud as part of our portfolio of Services.


Overlay