cookies, session management

Introduction

Recently, I had a challenge in our production system that was a bit annoying to figure out how to solve. Who knew that code can be deployed on a production environment and not work, even though it works on all other environments…

I did some digging and asked in forums what was the difference between session management on different environments on Salesforce Commerce Cloud (SFCC). Unfortunately I didn’t find anything, only limits and good practices that didn’t help in this case.

Well that’s life right? What do you do?? You decide to be pragmatic because a feature that works and is on the hands of real people, is far better than dreams of a perfect world.

The session problem

All you know is that attributes that you are saving on the SFCC platform’s session object, are not available where you need them. For the sake of this example, let’s say we are talking about a flow between the SFCC site and an API.

The code at the moment is something like this:

// apiGateway.js script
const apiResponse = { data: "something" };
session.privacy.myCustomField = JSON.stringify(apiResponse);

The flow starts by the site calling this API, and some time later receiving a callback from the API on a specific endpoint of SomeEndpoint.js controller. Then the site makes an API call to get data (specific to a given user) for further processing. Some of it is saved in the privacy field of the session object. As stated in SFCC docs, this field is a dictionary where we can store custom properties. The next step on the flow is to redirect to an action on the Login controller, and inside that action retrieve the information that was stored.

// SomeEndpoint.js controller
res.redirect(URLUtils.https("Login-Show"));

// Login-Show action
var apiResponse = session.privacy.myCustomField ? JSON.parse(session.privacy.myCustomField) : "";
// use apiResponse for further processing

The problem happens when running the Login-Show action, session.privacy.myCustomField is equal to null so we can’t retrieve the information that was saved in the previous controller, before the redirect.

Thinking about solutions

First you try to keep using the session object provided by SFCC, but saving the data on another field called custom. The difference between custom and privacy is that data inside custom won’t be deleted when the user logs out.

Then we try to think of another approach because storing in any field of the session might not work. So we try to store this information in Custom Objects (CO). It’s important to note a very important security detail with the custom objects approach. Creating and retrieving these custom objects happen in different controller actions. So in order for the second action to know how to retrieve the correct custom object that holds the API response data, it needs the ID for the CO.

Since moving from one action to the other happens through a redirect, we can only use query parameters. On top of that, the second action is Login-Show which renders HTML to the client in the end. Which means this custom object ID is publicly available in the user’s address bar… not good! This of course means you could simply type an ID in the URL and try to find a valid custom object containing some user’s data. Of course in the Login-Show action we can retrieve the custom object and delete it afterwards. But there is still a window where this data is accessible.

In order to prevent this exploit, we add code on the Login-Show action to validate the user accessing the login page is on the same session that initiated the login flow… but wait, did I just say “same session”. If we are having problems with this session not being the same, how can we guarantee validating this sessionID will work?? We have no guarantees basically.

After a lot of thinking, experimenting and reading docs, we decide to contact Salesforce by opening a support ticket. After that we were able to schedule a meeting and showed our problem. They investigated and got back to us with feedback on what was happening to the session, during the flow described earlier.

Final solution

The final solutions is… to not change any code. The problem was the hostname that was configured in the API that called the site. We simply configured it with the correct URL, which is the same domain in which the site uses when calling this API. In order to keep the correct session in the login page after the redirect, we made these changes:

BEFORE: https://production-zone-digitmarket.demandware.net/on/demandware.store/Sites-Awesome-Site/pt_PT/SomeEndpoint-Action

AFTER: https://awesome-domain.com/on/demandware.store/Sites-Awesome-Site/pt_PT/SomeEndpoint-Action

Conclusion

Hopefully this post helped you know how session management works in Salesforce B2C Commerce Cloud. The moral of the story is: when code works everywhere except on one environment, it’s generally an environment configuration problem.

If you enjoyed this post or learned something from it, leave a comment with your thoughts.

LEAVE A REPLY

Please enter your comment!
Please enter your name here