Platform Cache – Using it to store the access token if there is no refresh token mechanism provided

In my last post, I explained pretty much about the Platform cache and that was more theoretical. This post explains a use case where I used the Platform cache in my project. I had a challenge while working on a 3rd party application integration using OAuth 2 where I couldn’t refresh the access token as this mechanism has not been implemented by the 3rd party application vendor. In order to keep the process run, I needed the access token every time which requires the user interaction to authorize the users.

I am assuming that you are aware of the Salesforce Platform Cache and it’s used. If you are not familiar with Platform Cache then I would suggest you, read my last post.

Let me explain my use case in more details before we jump over to the solution. I wanted to send details about a campaign to a 3rd party application and it requires access token in the authorization header which we get in the OAuth 2 flow. For sending info to 3rd party application, I created a VF page (SyncToDemoApp)  which calls an Apex method from the page action in order to send information to 3rd party server.

SyncToDemo Visualforce page which is attached to a button on Campaign

 <apex:page standardController="Campaign" extensions="SyncToDemoAppController" action="{!initSync}">
 </apex:page>

To initiate the sync process, I needed a different page where I can authorize the user and get the access token. As you know, we have a redirect URL configured on the 3rd party application server where users redirected with the authorize code. Just think of google integration with SF. I will explain the code of SyncToDemoAppController class later.

Your application sends a token request to the Google Authorization Server, receives an authorization code, exchanges the code for a token, and uses the token to call a Google API endpoint.

Visualforce page for authorization

 <apex:page standardController="Campaign" extensions="ConnectToAppController" action="{!getAccessToken}">
 </apex:page>

Apex Controller for the above page

public class ConnectToAppController {
   Private static FINAL String MY_CLIENT_ID;
   Private static FINAL String MY_REDIRECT_UI;
   Private static FINAL String MY_CLIENT_SECRET ;
   private String campaignId;
   public ConnectToAppController(ApexPages.StandardController controller) {
      campaignId = controller.getId();
   }

   public PageReference getAccessToken() {
 
      // Check if page has loaded after redirecting from the **mydemoapp**
      // If its loaded from the redirection then it must have an authorization code
      // If authorization code found in the URL then we will make an api callout to get the access token
      // Otherwise will redirect user to authorize url of the application
      String authorization_code = ApexPages.currentPage().getParameters().get('code');
      If(authorization_code == null) {
         // Get the authorization code
         PageReference authorizeUrl = new PageReference('https://auth.mydemoapp.com/oauth/authorize?client_id=' + MY_CLIENT_ID + '&redirect_uri=' + MY_REDIRECT_UI + '&response_type=code');
         return authorizeUrl;
      } 
      else {

         Http http = new Http();
         HttpRequest request = new HttpRequest();
         // Get the access token
         request.setEndpoint('https://auth.mydemoapp.com/oauth/token?client_id=' + CLIENT_ID + '&client_secret=' + CLIENT_SECRET + '&code=' + authorization_code + '&grant_type=authorization_code');
         request.setHeader('Content-Type', 'application/x-www-form-urlencoded');
         request.setMethod('POST');
         HttpResponse response = http.send(request);
         if (response.getStatusCode() == 200) {
            Map < String, Object > results = (Map < String, Object > ) JSON.deserializeUntyped(response.getBody());
            System.debug(results);
            // We will have to save these values in the cache for later use 
            Cache.Session.put(campaignId + 'accessToken', (String) results.get('access_token'), 300); // You can set this time as per your token expired time
            Cache.Session.put(campaignId + 'refreshToken', (String) results.get('refresh_token'), 300);
            // Access token is not supported by this app that's the main reason we are using the
            // Platform cache here
         }
         else {
            // To debug the error, you can add the message to show on the page here
            System.assert(false, response.getBody());
         }
         // Now, we will have to redirect user to the referrer page 
         // We are saving the referrer url in Platform cache
         // To get the referrer URL, we will have to get the value using the key

         PageReference referrer_page = (PageReference) Cache.Session.get(campaignId + 'referrerUrl');
         return referrer_page;
      }
   }
}

Now, I think we have almost covered the authorization part. We just need to do some intelligent work in SyncToDemoAppController class. Here, we will check for the access token in Platform Cache. If we get the null for access_token key then we will redirect the user to the authorization page.

SyncToDemoAppController  Apex class

public class SyncToDemoAppController {
   String campaignId;
   public SyncToDemoApp(ApexPages.StandardController controller) {
      campaignId = controller.getId();
   }
 
   public PageReference initSync() {

      // Check if access_token is found in the platform cache
      if(Cache.Session.get(campaignId + 'accessToken') == null) {
         // Set the referrer for this campaign 
         Cache.Session.put(campaignId + 'referrerUrl', ApexPages.currentPage());
         // Redirect user to authorization page
         return new PageReference('/apex/ConnectToApp?id=' + campaignId);
      }
      // You can call the api methods by setting the authorization 
      // header of your http request
     else {
        String accessToken = (String) Cache.Session.get(campaignId + 'accessToken');
        // API Callouts
        // If you get token expired response then again send user to authorize page
        return new PageReference('/' + campaignId);
     }
   }
}

I found this solution very useful where we don’t have a refresh token mechanism to renew the access token. If your app allows you to renew the access token then I would not recommend this solution.  Please do let me know if you have any suggestion/feedbacks.

Keep visiting SFCURE!

Salesforce Platform cache – A booster in the application performance and for the developers as well

If you ever been in Java and .Net development and have moved to salesforce then you must had been missing one feature which is Session Management. This is something which every Salesforce developer waited for so long. It’s quite close to what we have in other server programming languages but with some limitations due to the multitenant environment of Salesforce. Platform cache is a new arrow in SF dev’s quiver to increase the performance of an application. View state has been an issue if it comes to mobile development.  Now, it is a part of Salesforce since Winter’16 release so I thought to write a post about this.

Caching of data is primarily used to increase the app performance, for situations where you want to use same data across the multiple transactions. To solve this purpose, we have been using Visualforce view state and sometimes custom setting or custom objects but these ways have their own cost like decreasing the app performance. Platform cache is built on the application layer of the Salesforce infrastructure which abstracts away all the tedious stuff. Platform cache would be very significant in many use cases and few of them which I can think of at the moment are the following –

  • To display data based on filters applied by any user over initially queried data
  • To manage the menus in navigation bars based on the user profiles
  • To create the custom login functionality on force.com sites as cookies are not a secure way to achieve it
  • To keep user-specific information across the Visualforce pages
  • To store access token in OAuth 2.0 implementation of 3rd party apps
  • Wherever passing values in URLs  are not secure

Platform Cache can be controlled using a simple API in apex. It also provides a built-in way to retrieve cached values in Visualforce page and in declarative formulas. Platform cache comes with 2 different varieties and each has its own features and its beauty of salesforce.

Session Cache – For each user with their own space and persistence

As the name implies, the Session cache is built for the individual user session where each user has their own space and can not be altered by any other user. This can be used where you want to keep the information related to logged in user for temporary uses. As a developer, you don’t need to store that information mapped with user’s session Id as Platform API take care of that. For example, your app is used by the field users very frequently to get the work order details. To increase the performance, you can get the data queried initially and keep that data in the Session cache for further filtration. Session cache expires when its specified time-to-live (ttlsecs value) is reached or when the session expires after eight hours, whichever comes first.

Org Cache – For all the users with shared space and persistence

This cache type is available for all the users and can be used across the application. This is useful where you want to have the same set of data for all the users.  For example, Keeping the access token which is frequently used in a API call to the third party system.  Org cache expires when its specified time-to-live (ttlsecs value) is reached.

Cache Management – To manage your cache uses

Platform cache can be divided into a partition and each partition can be used for a specific purpose. It’s same as we used to have the different partition of a HDD in our windows machine. Salesforce imposed some limitations to better utilization of this feature due to its multitenant environment. You can use up to 10 MB overall cache in the enterprise edition.

platform cache.png

Platform cache API – Get/Put values in apex

Platform API uses Cache namespace in which there are some classes are defined. Org and Session class is one of them which have get and put methods.

Put value in Org and Session cache
Cache.Org.put(KEY, VALUE, TIME_IN_SECONDS); - Store a value in Org cache
Cache.Session.put(KEY, VALUE, TIME_IN_SECONDS); - Store a value in Session cache
Get value from Org and Session cache
Cache.Org.get('KEY') - Returns an object which can be typecast
Cache.Session.get('KEY') - Returns an object which can be typecast

 

Platform cache should be used wherever it’s necessary and retrieving values are expensive. Instead of cached everything, this should be used wisely like this your last weapon on your list.

In next post, I will use a common use case where this can be used. Stay tuned with SFCure 🙂

Validate Visualforce form in lightning speed using VFValidator

While working on custom development, I found that form validation is the essential need for any developer in terms of data quality. I took a couple of hours to write code for the validation whether it is client side or server side and which gave me an idea to come up with a generic solution which can be used by any developer. To come up with a generic solution, I created one Visualforce component which can be embedded in any Visualforce page to validate the form.

Using VFValidator, you can do the common form validations. I am trying to evolve this as much as I can. I will try to keep my post very simple so everyone can be benefitted.

How to use VFValidator

Using VFValidator is very straightforward and quick. You just need to embed the VF component in your Visualforce page. Here is the syntax.

<c:VFValidator formId="FORM_ID"/>

FORM_ID : Form where you want to have the validation. 
By default its "frm" if you are not passing the ID.

After embedding the component, you will have to use some specific classes with your input components. Each class has its own purpose and there are limited classes which you can use. Here are the details about each class and its purpose.

  • required : To make a field required
  • email : To check the validity of the email address
  • phone :  To verify a valid phone number, only allows 123-456-7890 format
  • number  : To restrict field for digits only
  • password: To check the password strength, Must be 8 characters and must contain 1 digit and special character

VFValidator Sample code

<c:VFValidator></c:VFValidator>
<apex:inputText id="firstName" styleClass="required slds-input" value="{!Contact.FirstName}"/>

Screenshot_1.png

If you want to check the demo of VFValidator then here is the VFValidator DEMO Link. I have also created a GitHub repository.

Please feel free to give your feedback. Thanks in advance!!