DeloitteEngineering Blog | Netherlands

Working with Salesforce for React Native developers

Cover

At Deloitte, we work with several software platform vendors to provide solutions for our clients. Building on top of platforms that provide many features out of the box allows us to focus more on specific client needs and less on technical boilerplate. One of the vendors we work with often is Salesforce, who offer an extensive cloud platform.

To make these platforms accessible on mobile we develop apps that integrate with different backend systems. When using Salesforce as a backend, the company provides a Mobile SDK. It provides tight integration with their platform while still having the full flexibility of native development. It comes in multiple flavors (iOS, Android, React Native & Cordova) and contains features such as authentication, offline data storage and data synchronization.

The Mobile SDK is very helpful when the rest of the app’s architecture fits with how it works, i.e. direct synchronization of SObjects via Mobile Sync. However, it also comes with some downsides when working on a React Native app:

Not all apps require all functionality the Mobile SDK provides. Authentication and performing API requests may be enough. If you decide that it is not right for your project, there’s an alternative way of working with Salesforce.

Authenticating with Salesforce

Authenticating with Salesforce is done via OAuth. There’s a couple of libraries such as react-native-app-auth or expo-auth-session that help using OAuth in React Native. Either of these libraries is easily integrated with any React Native project, avoiding many of the code changes required by the Salesforce SDK and difficulties with CocoaPods.

Obtaining the proper configuration is done via the following this guide from Salesforce with the note that the “Consumer Key” in Salesforce is the client ID used by OAuth. Note that “Require Secret for Web Server Flow” must be disabled (usage of client secrets also isn’t recommended for mobile clients according to the guidelines). Once authentication is complete and the chosen OAuth library returns with the users’ access and refresh token, these can be persisted using libraries such as react-native-keygen or expo-secure-store in the devices’ encrypted storage.

Using these credentials, it’s time to send authenticated requests to your Salesforce instance. Handling HTTPS requests is easily done via built-in fetch with the appropriate headers set, example:

const accessToken = await SecureStore.getItemAsync("accessToken"); 
const instanceUrl = "https://instance.my.salesforce.com";
const fetchUrl = instanceUrl + "/services/apexrest/...";
const method = "GET"; 

const response = await fetch(fetchUrl, {
  method,
  body: body !== undefined && method !== "GET" ? JSON.stringify(body) : undefined,
  headers: {
    Authorization: "Bearer " + accessToken,
    Host: instanceUrl.substring(8).toLowerCase(),
    "Content-Type": "application/json"
  },
}); 

Refreshing the tokens

All good things come to an end, and so do user sessions. After some amount of time, the access token will become invalid. This is signaled if making a regular request (see previous example) returns a HTTP status code 401. The refresh token obtained during authentication can then be used to obtain a fresh access token. In the process, the refresh token itself may also be refreshed according to the specification, so you must be ready for it. The newly obtained credentials must then be used for all subsequent requests. Example code:

const { accessToken, refreshToken } = await refresh(
  { ...authConfig, scopes: [] }, // authConfig is config used when authenticatin
  { refreshToken: currentRefreshToken }
);

// access token is a fresh token 
// refresh token is a fresh token OR null OR empty string 

And that’s all that is needed to perform requests with a Salesforce back-end! Usage of community-standard libraries and standard JavaScript gives full power over the process and is easier from a complexity and maintenance point of view.

Connecting these pieces, the next step is to write a communication layer that handles all requests to Salesforce. It handles authentication automatically by setting the appropriate headers. When it detects that the token needs to be refreshed (through a HTTP 401 response), it will attempt to refresh the sessions and retry the original request transparently.

Conclusion

When building a React Native app using a Salesforce back-end, think about the integration architecture and offline capabilities the app should have. If back-end communication is (mostly) done by syncing SObjects to and from the server, using the Salesforce Mobile SDK with MobileSync is a great approach. It will also give you offline support out of the box.

But, if the back-end exposes custom endpoints and/or offline capabilities are not required, a custom integration will be easier to maintain and imposes less restrictions on the standard React Native template.