Introduction
Salesforce provides a robust set of APIs that allow developers to interact with their platform programmatically. In this article, we’ll explore how to build a Salesforce Connected App for API integration using Node.js, the OAuth 2.0 Web Server Flow will be implemented.d
The YouTube Channels in both English (En) and French (Fr) are now accessible, feel free to subscribe by clicking here.
Prerequisites
The goal is to grant API access to a Salesforce account without providing any username and password pair, so this tutorial assumes you are familiar with Salesforce, the OAuth authorization protocol, and NodeJS.
Salesforce OAuth 2.0 Web Server Flow
The OAuth 2.0 flow is simple, and here are the authorization steps:
- The user wants to connect his Salesforce account.
- We send him an authentication URL to log himself into Salesforce.
- Once logged in, Salesforce sends us a code to the callback.
- We exchange that code to have an access token.
The access token can then be used as the authorization bearer token for any protected Salesforce API resources we would like to access.
Create a Salesforce Connected App
Basic Info
It’s very simple to create a Salesforce Connected App, let’s follow the below instructions:
- Log in to your Salesforce Developer account.
- Navigate to Setup on the top right, then search for the App Manager in the Quick Find box.
- Click on the New Connected App button.
You’ll have a page similar to the following, in which you have to provide your App basic info (App Name, API Name, and Contact Email):
OAuth Settings
Just down to the Basic Information area, you have the API (Enable OAuth Settings) panel, from there let’s enable OAuth Settings.
This section is crucial for Salesforce to know more about the integration you are building, so let’s provide more details as follows and click Save then Continue:
- The callback URL: This is a server URL called once the end-user is granted access to his Salesforce account via the OAuth flow. Let’s provide a secured URL since sensitive information will flow to it to complete the authorization mechanism.
- OAuth scopes: It’s the permissions your API requests access for, do remember to always select ONLY what you need to apply the principle of the least privilege. This means that if this integration is attacked by hackers, your whole Salesforce account won’t be at risk, but only the scopes specified.
The scopes selected are:
- Access unique user identifiers (openid): This scope allows the connected App to access the logged-in user’s unique identifier.
- Manage user data via APIs (api): This scope allows access to the current, logged-in user’s account using APIs, such as REST API and Bulk API. This value also includes access to Chatter REST API resources, so you may not need to select the chatter_api scope.
- Manage user data via Web browsers (web): This scope allows the app to use the access token on the web and allows access to customer-created Visualforce pages.
Note: we’ll change our callback URL once the NodeJS backend is deployed and accessible online.
Manage Consumer Details
From the Manage Connected Apps page, click on the Manage Consumer Details button, then copy your connected App consumer key and consumer secret for later use in a NodeJS project.
Salesforce OAuth 2.0 Integration in NodeJS
By this stage, you should have the connected App’s consumer key (client ID), consumer secret (client secret), and the callback URL (redirect URI).
Handle Sensible Credentials
Since the first two are sensible information, you should use a method like the one performed by the dotenv package to hide it from your source code at the deployment stage.
Feel free to install dotenv using the command npm install -S dotenv
and set it up in your main file like below:
require('dotenv').config();
Once done, we can create a .env file in our project, we have created a template for it called .env.sample whose content is below:
APP_DOMAIN=https://xxxx-yyyy-zzzz.ngrok-free.app # Localhost is not secured, deploy your backend online or try ngrok
SF_CLIENT_ID=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
SF_CLIENT_SECRET=YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY
Do remember to change the values with the ones of your connected App you created in the previous step.
Request an Authorization Code
For the OAuth flow to work, two important endpoints must be created on the NodeJS side, one that sends back the authentication URL that the user will follow to grant access to its Salesforce account, and the last is the callback that Salesforce will send sensitive info to once the access is granted.
Let’s install the jsforce package that we’ll use to make the process easier, it’s a JavaScript library that interacts with Salesforce’s API.
npm install jsforce -S
Let’s use our Salesforce connected App to set up an OAuth2 instance now:
const oauth2 = new jsforce.OAuth2({
// you can change loginUrl to connect to sandbox or prerelease env.
// loginUrl : 'https://test.salesforce.com',
clientId: process.env.SF_CLIENT_ID,
clientSecret: process.env.SF_CLIENT_SECRET,
redirectUri: `${process.env.APP_DOMAIN}/callback`,
});
By using an Express server, here’s the authentication URL endpoint:
app.get("/auth", function (req, res) {
const authURL = oauth2.getAuthorizationUrl({
scope: "api web openid chatter_api refresh_token",
});
res.redirect(authURL);
});
Note: Make sure to provide the scopes (permissions) that your connected App has access to, especially the ones your NodeJS App needs, or else the next use of that OAuth2 instance won’t work properly.
Request an Access Token
Once the connected App is approved, Salesforce sends back the authorization code requested in the previous step.
The callback endpoint to complete the authorization process by processing that code is below:
// Pass the received authorization code and get access token
app.get("/callback", function (req, res) {
const conn = new jsforce.Connection({ oauth2 });
const code = req.query.code;
conn.authorize(code, function (error, userInfo) {
if (error) {
console.error(error);
return res.status(400).send(error);
}
// Don't log sensible info in a production setup, this is just for illustration
// Now you have the access token, refresh token, and instance URL info
// Save them in the db or cache for later use/connection
console.log(conn.accessToken);
console.log(conn.refreshToken);
console.log(conn.instanceUrl);
console.log("User ID: " + userInfo.id);
console.log("Org ID: " + userInfo.organizationId);
res.send("success");
});
});
Salesforce API Requests in NodeJS
The jsforce library uses the access token to call Salesforce API resources on behalf of the logged-in user, it simplifies the API integration, read more here.
In our case, we simply wrote a message in Chatter by creating another endpoint like below:
app.get("/chatter", function (req, res) {
// Get the logged-in user's access/refresh token from the db or cache
const conn = new jsforce.Connection({ oauth2, instanceUrl: 'savedInstanceUrl', accessToken: 'savedAccessToken', refreshToken: 'savedRefreshToken' });
// Let's write in Chatter to test it out
conn.chatter.resource("/feed-elements").create(
{
body: {
messageSegments: [
{
type: "Text",
text: "This is a NEW post",
},
],
},
feedElementType: "FeedItem",
subjectId: "me",
},
function (error, result) {
if (error) {
console.error(error);
return res.status(400).send(error);
}
console.log("New comment of id: " + result.id);
res.send("OK");
}
);
conn.on("refresh", function (accessToken, res) {
// Refresh event will be fired when renewed access token
// TODO: do something here with the new access token: save it again
console.log("Access token refreshed: " + accessToken);
});
});
The full source code is available on GitHub.
Test
If you test it now, it won’t work because the NodeJS App isn’t yet linked with your connected App, because we have to fix the callback URL.
First, deploy your NodeJS backend using the domain where it’s located in the APP_DOMAIN environment variable present in the .env file.
Second, you have to change your Salesforce connected App settings to use the right callback URL: {APP_DOMAIN}/callback.
Finally, use another account to connect yourself to your App by following the OAuth2 process described above. The entry point is {APP_DOMAIN}/auth.
By testing everything, our NodeJS project {APP_DOMAIN}/chatter API endpoint output is:
Do you want to know more about Salesforce? Take a look at the What is Salesforce? article that we released recently:
Troubleshooting Salesforce OAuth 2.0
- Error mismatch: The consumer key, consumer secret, and callback URL you use in NodeJS should match what is present in the Salesforce App manager.
- If you get the error “1800 : There was a problem in setting up your remote access”, make sure the connected App you created and the user testing your App are both in the same environment.
Resources
- https://github.com/jsforce/jsforce
- https://help.salesforce.com/s/articleView?id=sf.remoteaccess_oauth_web_server_flow.htm&type=5
- https://help.salesforce.com/s/articleView?id=sf.remoteaccess_oauth_tokens_scopes.htm&type=5
- https://github.com/numerica-ideas/community/tree/master/salesforce/oauth2-web-server-flow
Let’s note that the jsforce npm package has a few basic maintenance commits over a long period and was maintained by only 1 person, so not sure you may receive great support if anything goes wrong in it … but there’s a great promise that way, as one of the Salesforce teams started to contribute to push jsforce forward since a lot of Salesforce open source tools rely on the jsforce package, here’s the official announcement.
———————
We have just started our journey to build a network of professionals to grow even more our free knowledge-sharing community that will give you a chance to learn interesting things about topics like cloud computing, software development, and software architectures while keeping the door open to more opportunities.
Does this speak to you? If YES, feel free to Join our Discord Server to stay in touch with the community and be part of independently organized events.
———————
Conclusion
In summary, this article unveiled the steps to securely integrate Salesforce with your NodeJS projects by using the OAuth 2.0 Web Server Flow by requesting an authorization code, allowing the user to approve the App, and then requesting the access token for later use in API requests.
Thanks for reading this article. Like, recommend, and share if you enjoyed it. Follow us on Facebook, Twitter, and LinkedIn for more content.