Sunday, April 21, 2024

OAuth 2.0 Web Server Flow to integrate two salesforce orgs

This flow is used to integrate an external web app with the Salesforce API, it implements the OAuth 2.0 authorization code grant type. With this flow, the server hosting the web app must be able to protect the connected app’s identity, defined by the client ID and client secret.

Throughout this topic, we'll dive into the key concepts of the Web Server Flow,  and provide a step-by-step guide on how to implement it between two Salesforce orgs say ORG A and ORG B.

By the end of this session, you'll have a clear understanding of how to leverage the Web Server Flow to create robust integrations that facilitate smooth collaboration and data sharing between Salesforce environments. Let's get started!

The below steps explain the process involved in webserver flow.

  • Request an Authorization Code
  • Authenticate the User and Grant Access to the App
  • Receive a Callback
  • Request an Access Token
  • Receive an Access Token

  • Post Request


Let's start,

ACTIVITIES WE NEED TO DO IN ORG B.

1) Create a Connected App in ORG B.

2) Create a Webservice in ORG B which will be invoked from ORG A.

Create A Connected App In ORG B:

The connected app configured above under "How to configure a Connected App for the OAuth 2.0 Client Credentials Flow?" will work for web server flow as well as we have also enabled "Require Secret for Web Server Flow" check box. The below image also highlights callback URL of ORG A.






Create A Webservice As Shown Below In ORG B:

The createAccountRecord class is an Apex REST service that allows external systems to create Account records in a Salesforce org. It is exposed as a REST resource with the URL mapping '/createAccountRecord/*', meaning it can be accessed via HTTP requests.

This service defines a POST method, createAccount(), which expects JSON data containing information about the Accounts to be created. Upon receiving a request, the method deserializes the JSON payload, creates Account records based on the provided data, and attempts to insert them into the database.

If the insertion is successful, the method returns 'Success'. Otherwise, it returns 'Failure'.

The incoming JSON payload should adhere to the structure defined by the responseWrapper inner class, which includes fields such as Name, Description, Type, and Industry for each Account record.

This REST service provides a simple yet effective means for external systems to programmatically create Account records in the Salesforce org, facilitating seamless integration and data synchronization.

@RestResource(urlMapping='/createAccountRecord/*')

   global with sharing class createAccountRecord {

     @HttpPost

      global Static string createAccount(){

      RestRequest req = RestContext.request;

      RestResponse res = Restcontext.response;

      string jsonString=req.requestBody.tostring();

      system.debug('jsonString'+jsonString);

      boolean successCheck;

      List<responseWrapper> wRespList=(List<responseWrapper>) JSON.deserialize(jsonString,List<responseWrapper>.class);

      Account obj=new Account();

      List<Account> accList= new List<Account>();

      for(responseWrapper wResp: wRespList){

      obj.Name=wResp.Name;

      obj.Description=wResp.Description;

      obj.Type=wResp.Type;

      obj.Industry=wResp.Industry;

      accList.add(obj);

      }

      try{

      if(accList.size() > 0){

      Insert accList;

      successCheck=true;

      }

      }

      catch(Exception e){

      successCheck=false;

      }

      if(successCheck)

      return 'Success';

      else

      return 'Failure';

      }

 

      global class responseWrapper{

 

       global string Name;

       global string Description;

       global string Type;

       global string Industry;

 

      }

 

   }


ACTIVITIES WE NEED TO DO IN ORG A.

Request an Authorization Code:

Hit the below URL to get the authorization code.

https://farukh-dev-ed.lightning.force.com/services/oauth2/authorize?
client_id=Client_Id_Of_ConnectedApp_From_OrgB&
redirect_uri=https://myknowndomain-dev-ed.my.salesforce.com/services/oauth2/callback&
response_type=code

If you’re not familiar with these types of calls, don’t worry. Let’s break it down into its individual components.

Component 1:

https://farukh-dev-ed.lightning.force.com/services/oauth2/authorize

This address is the Salesforce instance’s OAuth 2.0 authorization endpoint of ORG B. It’s the endpoint where your connected apps send OAuth authorization requests.

Component 2:

client_id=Client_Id_Of_ConnectedApp_From_OrgB

The client ID is the connected app’s consumer key from ORG B.

Component 3:

redirect_uri=https://myknowndomain-dev-ed.my.salesforce.com/services/oauth2/callback

The redirect URI is where users are redirected after a successful authorization. In our case it corresponds to ORG A callback URL. The redirect URI is the connected app’s callback URL, which you can also find on the connected app’s Manage Connected Apps page.

This image shows the callback URL that corresponds with the code samples.



Component 4:

response_type=code

The response type tells Salesforce which OAuth 2.0 grant type the connected app is requesting. The response type of code indicates that the connected app is requesting an authorization code.

After you successfully hit the URL, you will be asked to login into Salesforce ORG B. One you logged in with ORG B credentials you will be redirected to below URL as shown below. As you can see the below URL has auth code as highlighted.

https://myknowndomain-dev-ed.my.salesforce.com/services/oauth2/callback?code=aPrxsh*********************************************8Xg%3D%3D

Now, next step is to get the access token and do callout to ORG B to POST account creation request using the auth code obtained above.

The provided code demonstrates an integration scenario where an Apex class interacts with Salesforce REST APIs to perform various operations, such as obtaining an access token, querying data, and making callouts to another Salesforce org.

Here's a breakdown of the key functionalities:

responseWrapper Class: Defines a wrapper class to represent the response from the OAuth token request. It includes fields such as id, access_token, and instance_url.

cKey and cSecret: Variables to store the client ID and client secret obtained from a Custom Metadata Type named Store_Cred__mdt.

Connection Parameter Retrieval: Retrieves the client ID and client secret from the Store_Cred__mdt Custom Metadata Type.

Authentication Code and URI: Defines the authorization code and redirect URI required for the OAuth token request.

Request Body Construction: Constructs the request body for the OAuth token request including the grant type, client ID, client secret, authorization code, and redirect URI.

OAuth Token Request: Sends a POST request to the OAuth token endpoint to obtain an access token using the constructed request body.

Deserialization: Deserializes the response from the OAuth token request into the responseWrapper class.

API Callout: Constructs a callout request to another Salesforce org's Apex REST endpoint (createAccountRecord) to create an Account record.

Setting Headers and Body: Sets the necessary headers (Authorization and Content-Type) and request body for the callout.

Sending Callout Request: Sends the callout request to create an Account record in the target Salesforce org.

Handling Response: Checks the response status code to determine if the callout was successful.

This code demonstrates a typical integration flow where Salesforce Apex code interacts with Salesforce REST APIs to authenticate, exchange data, and perform operations across different Salesforce orgs.

Copy paste the below code in execute anonymous window in ORG A and replace the authCode with the authCode obtained above during authorization request.

public class responseWrapper {

        public string id;

        public string access_token;

        public string instance_url;

    }

public string cKey;

public string cSecret;

List < Store_Cred__mdt > connectionParam = [SELECT Id, MasterLabel, client_id__c, client_secret__c from Store_Cred__mdt];

        if(connectionParam.size() >0){

        cKey=connectionParam[0].client_id__c;

        cSecret=connectionParam[0].client_secret__c;

        }

        System.debug('Store_Cred__mdt' + connectionParam);

        String authCode= 'aPrxsh*********************************************8Xg%3D%3D';

         // The below URI is the callback URL of ORG A

        String uri='https://myknowndomain-dev-ed.my.salesforce.com/services/oauth2/callback';

        String reqBody = 'grant_type=authorization_code&client_id=' + cKey + '&client_secret=' + cSecret + '&code=' + authCode + '&redirect_uri=' + uri ;

        Http h = new Http();

        HttpRequest req = new HttpRequest();

        req.setBody(reqBody);

        req.setMethod('POST');

       // Token end point of  ORG B

        req.setEndpoint('https://farukh-dev-ed.my.salesforce.com/services/oauth2/token');

        HttpResponse hresp = h.send(req);

        System.debug('hresp is'+hresp);

        System.debug('hresp body is'+hresp.getBody());

        responseWrapper wResp = (responseWrapper) JSON.deserialize(hresp.getBody(), responseWrapper.class);

        system.debug('reqBody '+reqBody );

        system.debug('wResp'+wResp );

        system.debug('Instance url' + wResp.instance_url);

        system.debug('session id' + wResp.access_token);

 

         List<Account> accList = new List<Account>();

// End point of ORG B where we will send POST request for account record creation

string endPoint = 'https://farukh-dev-ed.my.salesforce.com'+'/services/apexrest/createAccountRecord';

             accList=[SELECT Id,Name,Description,Type,Industry from account Order By createddate DESC Limit 1];

         Http h1 = new Http();

            HttpRequest req1 = new HttpRequest();

            req1.setHeader('Authorization', 'Bearer ' + wResp.access_token);

            req1.setHeader('Content-Type', 'application/json');

            req1.setMethod('POST');

            req1.setEndpoint(endPoint);

            req1.setBody(JSON.serialize(accList));

            HttpResponse hresp1 = h1.send(req1);

            system.debug('hresp1'+hresp1 );

            system.debug('hresp1.getStatusCode()'+hresp1.getStatusCode());

             system.debug('hresp1.getBody()'+hresp1.getBody());

            if (hresp1.getStatusCode() == 200) {

                system.debug('Callout Success');

            }


After executing the above code from developer console, the below image shows the log. You can also verify the account record will be created in ORG B.


Account record created in ORG B.



Saturday, March 30, 2024

Explain Javascript Async/Await?

"async and await make promises easier to write". async makes a function return a Promise while await makes a function wait for a Promise

Async Syntax:

The keyword async before a function makes the function return a promise:

Example:

async function myFunction() {

  return "Hello";

}

The above is the same as below:

function myFunction() {

  return Promise.resolve("Hello");

}

Await Syntax:

The await keyword can only be used inside an async function.

The await keyword makes the function pause the execution and wait for a resolved promise before it continues:

let value = await promise;

Let us understand this with an example,

function myFunction(some) {

  console.log('Inside myFunction');

}

async function promiseDemonstration(){

let myPromise = new Promise(function(myResolve, myReject) {

   let x = 0;

  if (x == 0) {

    myResolve("OK");

    console.log('Inside If');

    setTimeout(myFunction , 3000);

  } else {

    console.log('Inside else');

    myReject("Error");

  }

});

let value = await myPromise;

console.log('Awaiting Promise'+value);

myPromise.then(

  function(value) {

    console.log('Inside Value');

    myFunction(value);},

  function(error) {

    console.log('Inside Error');

    myFunction(error);}

);

}

promiseDemonstration();

Explain JavaScript Promise Object?

As we have seen earlier, With asynchronous programming, JavaScript programs can start long-running tasks, and continue running other tasks in parallel.

But, asynchronus programmes are difficult to write and difficult to debug.

Because of this, most modern asynchronous JavaScript methods don't use callbacks. Instead, in JavaScript, asynchronous programming is solved using Promises instead.

A Promise contains both the producing code and calls to the consuming code:

Promise Syntax:

let myPromise = new Promise(function(myResolve, myReject) {

// "Producing Code" (May take some time)

  myResolve(); // when successful

  myReject();  // when error

});

// "Consuming Code" (Must wait for a fulfilled Promise)

myPromise.then(

  function(value) { /* code if successful */ },

  function(error) { /* code if some error */ }

);

When the producing code obtains the result, it should call one of the two callbacks:

When     Call

Success     myResolve(result value)

Error     myReject(error object)

Promise Object Properties:

A JavaScript Promise object can be:

Pending

Fulfilled

Rejected

The Promise object supports two properties: state and result.

While a Promise object is "pending" (working), the result is undefined.

When a Promise object is "fulfilled", the result is a value.

When a Promise object is "rejected", the result is an error object.

myPromise.state      myPromise.result

"pending"      undefined

"fulfilled"      a result value

"rejected"      an error object

Let us understand the use of Promise with an example:

function displayValue(some) {

 console.log('Inside displayValue');

}

let myPromise = new Promise(function(myResolve, myReject) {

  let x = 0;

// The producing code (this may take some time)

  if (x == 0) {

    myResolve("OK");

  } else {

    myReject("Error");

  }

});

myPromise.then(

  function(value) {displayValue(value);},

  function(error) {displayValue(error);}

);

Output:

Inside displayValue


Let us understand the use of Promise with setTimeout.

Example Using Callback:

setTimeout( myFunction, 1000);

function myFunction() {

  console.log('Inside myFunction');

}

Output:

Inside myFunction

Example Using Promise:

function myFunction(some) {

  console.log('Inside myFunction');

}

let myPromise = new Promise(function(myResolve, myReject) {

   let x = 1;

  if (x == 1) {

    myResolve("OK");

    console.log('Inside If');

    setTimeout(myFunction , 3000);

  } else {

    console.log('Inside else');

    myReject("Error");

  }

});

myPromise.then(

  function(value) {

    console.log('Inside Value');

    myFunction(value);},

  function(error) {

    console.log('Inside Error');

    myFunction(error);}

);

Output:

Inside If
Inside Value
Inside myFunction

What are classes in Javascript and explain Inheritance?

A JavaScript class is not an object. It is a template for JavaScript objects. Use the keyword class to create a class. 

Always add a method named constructor().

class Employee {

  constructor(name, department) {

    this.name = name;

    this.department = department;

  }

}

The example above creates a class named "Employee".

The class has two initial properties: "name" and "department".

The example below uses the Employee class to create a Employee object.

const myEmp = new Employee("Farukh", IT);

The constructor method is called automatically when a new object is created. The constructor method is a special method.

It has to have the exact name "constructor".

Sample Example to demonstrate class use:

class Employee {

  constructor(name, department) {

    this.name = name;

    this.department = department;

  }

  displayValue() {

    console.log('Name is '+this.name);

    console.log('department is '+this.department);

  }

}

const myEmp = new Employee("Farukh", "IT");

myEmp.displayValue();

Output:

Name is Farukh

department is IT

Class Inheritance:

To create a class inheritance, use the extends keyword.

A class created with a class inheritance inherits all the methods from another class:

class Employee {

  constructor(name, department) {

    this.name = name;

    this.department = department;

  }

}

class Manager extends Employee {

  constructor(name, department, position) {

    super(name, department);

    this.position = position;

  }

  displayValue() {

    console.log('Name is '+this.name);

    console.log('department is '+this.department);

    console.log('position is '+this.position);

  }

}

const myEmp = new Manager("Farukh", "IT", "Consultant");

myEmp.displayValue();

Output:

Name is Farukh

department is IT

position is Consultant

The super() method refers to the parent class.

By calling the super() method in the constructor method, we call the parent's constructor method and gets access to the parent's properties and methods.

Explain JavaScript Callbacks?

 A callback is a function passed as an argument to another function.

In the below example, we can see we are passing displayValue function as an argument to doSum function while calling doSum function.

doSum(2, 3, displayValue);

function displayValue(sum) {

  console.log('callback function called');

  console.log('Sum is '+sum);

}

function doSum(num1, num2, sampleCallbackDemonstration) {

  let sum = num1 + num2;

  sampleCallbackDemonstration(sum);

}

Output:

callback function called

Sum is 5

Note: When you pass a function as an argument, remember not to use parenthesis.

When to Use a Callback?

They above example is to understand the callback syntax.

Where callbacks really shine are in asynchronous functions, where one function has to wait for another function like waiting for a file to load.

In the real world, callbacks are most often used with asynchronous functions.

A typical example is JavaScript setTimeout().

setTimeout(myFunction, 3000);

function myFunction() {

  // some code here

}

In the example above, myFunction is used as a callback.

myFunction is passed to setTimeout() as an argument.

3000 is the number of milliseconds before time-out, so myFunction() will be called after 3 seconds.

With asynchronous programming, JavaScript programs can start long-running tasks, and continue running other tasks in parallel. But, asynchronus programmes are difficult to write and difficult to debug.Because of this, most modern asynchronous JavaScript methods don't use callbacks. Instead, in JavaScript, asynchronous programming is solved using Promises instead.