Introduction
In today's interconnected world, seamless integration between different systems is crucial for businesses to operate efficiently and provide a superior user experience. The integration of Google REST API with Salesforce brings together the power of two leading platforms, enabling organizations to leverage the capabilities of both systems and unlock new possibilities.
This article dives into the realm of integrating Google REST API with Salesforce, focusing on the OAuth 2.0 authentication mechanism provided by Google and leveraging Salesforce's Auth. Provider and Named Credentials features. By combining these technologies, businesses can establish a secure and streamlined connection between Google services and their Salesforce org, opening up a world of possibilities for data synchronization, automation, and enhanced productivity.
Google side steps
1. Log in to https://console.cloud.google.com.
2. Select Project and click New Project.
3. Enter a Project name, Organization, and Location if needed, and click Create.
4. In the project dashboard, click the menu icon in the upper left, and then click APIs & Services.
5. Click +Enable Apis And Services.
6. Search and click on the API you need to integrate with. In my example, it will be Google Drive API.
7. Click Enable.
8. Click OAuth Consent Screen in the menu on the left side.
9. Check the User Type option you need and click Create.
10. Enter all required information and click Save and Continue.
11. On the next screen add scopes for your app according to your API. You can find proper scopes here. For my case, I added the following scope - ‘https://www.googleapis.com/auth/drive’. Click Save and Continue.
12. Review your settings and click Back to Dashboard.
13. Click Credentials in the menu on the left side. In the new tab click Create Credentials, and select OAuth Client Id.
14. Select the Application type as a Web application, give it a name, keep Authorized redirect URIs empty for now, and click Create.
15. Copy the Client Id and Client Secret after creation.
Salesforce side steps
1. From Setup search for Auth. Providers in the Quick Find box and then select Auth. Providers. Click New to create a new record.
2. Set Google as Provider Type, enter Name, URL Suffix, Consumer Key and Secret copied in step 15 on Google side, enter Default Scopes - ‘openid’, plus permissions that will be used by this provider (‘https://www.googleapis.com/auth/drive’ in my case).
Fill Authorize Endpoint URL with the following value: ‘https://accounts.google.com/o/oauth2/auth?access_type=offline&approval_prompt=force’ - it will tell Google to give us back a refresh token which will be used to avoid authentication over and over again. Click Save.
3. After saving, copy the Callback URL from the Salesforce Configuration section.
4. Go back to Google Web Application created in step 14 on the Google side.
5. Choose to Add URI under the Authorized redirect URIs section and paste Callback URL copied in the previous step. Click Save.
Google Project and Auth. The provider is set. Now we need to create Named Credentials that will be used in Apex to access Auth. Provider which authorizes us in Google Project.
6. From Setup search for Named Credentials in the Quick Find box and then select Named Credentials. Click New Legacy to create a record.
7. Enter Label, Name, URL (NOTE: this URL will be used as base URL in your API calls in Apex, use ‘https://www.googleapis.com’ for the common case), set Identity Type as Named Principal, Per User or Anonymous according to your case (A Named Principal applies the same credential or authentication configuration for the entire org, while Per User authentication provides access control at the individual user level. Anonymous principal identities are typically used for public or open APIs that do not require authentication or authorization).
Set Authentication Protocol as OAuth 2.0, and enter Authentication Provider created in step 2. Enter Scopes if you want to redefine the scopes entered in Auth. Provider. Keep Start Authentication Flow on Save checked if you have chosen Named Principal as Identity Type. Click Save.
8. After saving you will be redirected to the Google authorization page. Choose Google account you want to use
9. You will be asked to allow access to Scopes defined whether in Named Credentials or Auth. Provider. Click Allow.
10. After that you will be redirected back to the Named Credentials page. Check Authentication Status.
11. For flexibility we will create a Custom Setting which will be used by the Apex class. From Setup search for Custom Settings in the Quick Find box and then select Custom Settings. Click New to create a new record. Enter the Label and Object Name. Click Save.
12. After saving, click New in the Custom Fields tab. Select Text as field type, enter ‘Named Credentials Name’ as Label, ‘Named_Credentials_Name’ as Field Name. Click Next and Save.
13. Click Manage and create a new Default Organization Level Value. Populate Named Credentials Name field with a name of Named Credentials name (not label) created in steps 6-7.
That’s it! Writing Apex class making Google REST API calls is left.
14. Create Apex class to make Google API calls. In my example I will create a class that retrieves files from the specific folder by folder id. This class uses Default Organization Level Value of Custom Setting created in a previous step. So if you want to change Named Credentials for the Apex class you don’t need to change the code, just change Default Organization Level Value for the used Custom Setting.
public with sharing class GoogleDriveFolderViewerController {
public static final String FOLDER_MIMETYPE = 'application/vnd.google-apps.folder';
public static final String SLASH_SYMBOL = '/';
public static final String FIELDS_DEFAULT_SCOPRE = '*';
public static final String EMPTY_SETTING_ERROR_MESSAGE = 'Google_Drive_Folder_Viewer custom setting org defaults is empty';
private static Google_Drive_Folder_Viewer__c setting = Google_Drive_Folder_Viewer__c.getOrgDefaults();
@AuraEnabled
public static List<GoogleDriveFile> getFiles(String folderId) {
checkCustomSetting();
String method = 'GET';
String endpoint = '/files';
String query = 'mimeType!=\'' + FOLDER_MIMETYPE + '\' and trashed=false and \'' + folderId + '\' in parents';
String fields = 'files(id, name)';
String responseBody = makeCallout(method, endpoint, query, fields);
Map<String, Object> jsonMap = (Map<String, Object>) JSON.deserializeUntyped(responseBody);
List<GoogleDriveFile> files = (List<GoogleDriveFile>) JSON.deserialize(JSON.serialize(jsonMap.get('files')), List<GoogleDriveFile>.class);
return files;
}
private static void checkCustomSetting() {
if(setting == null || setting?.Named_Credentials_Name__c == null) {
throw new Exception(EMPTY_SETTING_ERROR_MESSAGE);
}
}
private static String makeCallout(String method, String endpoint, String query, String fields) {
fields = fields == null ? 'fields=' + FIELDS_DEFAULT_SCOPRE : 'fields=' + EncodingUtil.urlEncode(fields, 'UTF-8');
endpoint = endpoint.charAt(0) == SLASH_SYMBOL.charAt(0) ? endpoint : SLASH_SYMBOL + endpoint;
query = 'q=' + EncodingUtil.urlEncode(query, 'UTF-8');
HttpRequest request = new HttpRequest();
request.setMethod(method);
request.setEndpoint('callout:' + setting.Named_Credentials_Name__c + endpoint + '?' + query + '&' + fields);
Http http = new Http();
HTTPResponse response = http.send(request);
if (response.getStatusCode() == 200) {
return response.getBody();
} else {
throw new CalloutException(response.getBody());
}
}
public class GoogleDriveFile {
@AuraEnabled public String id;
@AuraEnabled public String name;
public GoogleDriveFile(String id, String name) {
this.id = id;
this.name = name;
}
public GoogleDriveFile() {
}
}
}
15. Create a LWC to call Apex class.
import { LightningElement, api, wire } from 'lwc';
import getFiles from '@salesforce/apex/GoogleDriveFolderViewerController.getFiles';
export default class GoogleDriveFolderViewer extends LightningElement {
@api folderUrl;
@api folderId;
files = [];
errorMessage = null;
connectedCallback() {
if(this.folderId == null) {
this.folderId = getFolderIdFromUrl(this.folderUrl);
}
if(this.folderId != null) {
this.getFiles(this.folderId);
} else {
this.errorMessage = ‘Folder Id or Folder URL need to be presented’;
}
}
getFolderIdFromUrl(folderUrl) {
if(folderUrl == null) {
return null;
}
let urlParts = folderUrl.split('/');
return urlParts[urlParts.length-1];
}
getFiles(folderId) {
getFiles({folderId: folderId})
.then(result => {
this.files = result;
})
.catch(error => {
this.errorMessage = error.body.message;
})
}
}
Conclusion
As we conclude our exploration of integrating Google REST API with Salesforce, it's evident that this integration opens up a world of opportunities for businesses. By leveraging the OAuth2 authentication mechanism from Google and Salesforce's Auth.Provider and Named Credentials, organizations can seamlessly connect and exchange data between these two powerful platforms.
Through this integration, businesses can automate processes, streamline workflows, and gain deeper insights by harnessing the combined strengths of Google and Salesforce. Whether it's synchronizing customer data, leveraging Google services within Salesforce, or enhancing productivity through automation, the possibilities are endless.
As you embark on your integration journey, remember to adhere to security best practices, carefully manage authentication and authorization, and thoroughly test your integration to ensure its reliability and performance.
Integrating Google REST API with Salesforce empowers organizations to harness the full potential of these platforms, unlocking new levels of productivity, efficiency, and data-driven decision-making. Embrace this integration, and discover the transformative power it brings to your business operations.