<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: kashyap </title>
    <description>The latest articles on DEV Community by kashyap  (@kashyap_kalakbandi).</description>
    <link>https://dev.to/kashyap_kalakbandi</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F605234%2F8c06ed2d-c4d2-455c-919d-e6f6aa42c17c.jpg</url>
      <title>DEV Community: kashyap </title>
      <link>https://dev.to/kashyap_kalakbandi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kashyap_kalakbandi"/>
    <language>en</language>
    <item>
      <title>Retrieve Voice transcripts programmatically.</title>
      <dc:creator>kashyap </dc:creator>
      <pubDate>Thu, 28 Apr 2022 05:04:52 +0000</pubDate>
      <link>https://dev.to/kashyap_kalakbandi/retrieve-voice-transcripts-programmatically-4nla</link>
      <guid>https://dev.to/kashyap_kalakbandi/retrieve-voice-transcripts-programmatically-4nla</guid>
      <description>&lt;h2&gt;
  
  
  Usecase
&lt;/h2&gt;

&lt;p&gt;You have a functioning service cloud voice product configured in your org and you would like to retrieve the transcripts programmatically to further use them with Einstein API (or) Providing Recommendations via NBA . (here , I am consuming this in a LWC component) &lt;/p&gt;

&lt;h3&gt;
  
  
  Details
&lt;/h3&gt;

&lt;p&gt;While there are many options on how to use the transcripts fetched, We will focus on the "fetching" part of transcriptions. i.e. We will focus on how to retrieve these transcriptions programmatically and what is needed for that. &lt;br&gt;
The retrieved data then can be consumed by LWC / Aura or Visualforce page as per your requirements.&lt;/p&gt;
&lt;h3&gt;
  
  
  Pre-requisites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Service Cloud Voice enabled org. &lt;br&gt;
(Here I am using Service Cloud voice with Amazon Telephony model where                 Amazon connect comes bundled with SCV product)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rest API (Enabled by default) end point for Transcription&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Documentation for reference [ &lt;a href="https://developer.salesforce.com/docs/atlas.en-us.chatterapi.meta/chatterapi/connect_resources_conversation_entries.htm" rel="noopener noreferrer"&gt;ConnectAPI's ConversationEntries&lt;/a&gt;]&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Apex Programming (Basics,Making callouts, Understanding of a JWT token)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Steps Outline
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;JWT Token&lt;/li&gt;
&lt;li&gt;Callout to ConversationEntry endpoint by passing ConversationIdentifier (VendorCallKey)&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Let's get Started !
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Why JWT Token ?&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Since we cannot query the Entries directly via SOQL, we are using REST API to retrieve those. To do this, we would need to authenticate ourselves to access the data. &lt;br&gt;
We have to use one of the auth flows to get access token for that. And, JWT is the opted approach. &lt;/p&gt;

&lt;p&gt;Wait, I am making a callout from Apex (Used by a Lightning Web Component) to the REST API endpoint of the same org. Do I still need to authenticate again? &lt;br&gt;
Answer is Yes, Also, We cannot use Lightning sessions to access REST APIs. You would see an INVALID_SESSION error. &lt;/p&gt;

&lt;p&gt;Now there is a Hack , I have tried creating a visualforce page and adding Api Global Variable to get the session Id like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;apex:page&amp;gt;
##{!$Api.Session_ID}##
&amp;lt;/apex:page&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and then, and then call getContent(thatvfpage) from Apex to get a page that contains an API-capable session ID, which we should be able to use (parsing out ##..##).&lt;/p&gt;

&lt;p&gt;However, this doesn't seem to work. So, my next best option was to perform JWT authentication , retrieve the token and use it as this doesn't need user interaction to authenticate the user. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Step-1    JWT Token&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Step-1A : Create a Signed Certificate and Key&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The OAuth 2.0 JWTbearer authorization flow requires a digital certificate and the private key used to sign the certificate.&lt;br&gt;
This is pretty straight forward and can be done following this doc [&lt;a href="https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_auth_key_and_cert.htm" rel="noopener noreferrer"&gt;Create a Private Key and Self-Signed Digital Certificate&lt;/a&gt;]&lt;br&gt;
--&amp;gt; We only need the certificate and key file &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step-1B : Upload this certificate in Files&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Go to App Launcher &amp;gt; Files &amp;gt; Upload files  &amp;gt; (upload the certificate generated). Assuming the name of file is Server&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step-1C : Create a Connected App and upload the certificate create in Step-1B&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is required as you would be using the certificate for authenticating via this connected app.  Provide proper scopes and call back URL can be anything (eg: &lt;a href="http://localhost:1717/OauthRedirect" rel="noopener noreferrer"&gt;http://localhost:1717/OauthRedirect&lt;/a&gt;) &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step-1D: Write an apex class to handle JWT authentication.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://help.salesforce.com/s/articleView?id=sf.remoteaccess_oauth_jwt_flow.htm&amp;amp;type=5" rel="noopener noreferrer"&gt;Refer the Documentation here&lt;/a&gt; if you want to try this out.&lt;/p&gt;

&lt;p&gt;If you are not aware of the entire logic, No worries ! - You can refer &lt;a href="https://github.com/kashyapkbandi/oauthflows/blob/master/JWTUtils.apxc" rel="noopener noreferrer"&gt;&lt;strong&gt;this git repo code&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;
which I have written for a visualforce page.  The Logic will be still the same.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quick Explanation of the code:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;retrievePKContent -&amp;gt; Is responsible to fetch the content of the certificate we uploaded in Step-1B and stripping off the -----BEGIN RSA PRIVATE KEY----- and -----END RSA PRIVATE KEY-----  strings. &lt;/li&gt;
&lt;li&gt;createHeader -&amp;gt; Just creates JWT header with algorithm name&lt;/li&gt;
&lt;li&gt;base64URLencode  -&amp;gt; This is to encoding blob input to base64&lt;/li&gt;
&lt;li&gt;generateJsonBody -&amp;gt; This generates JSON body for the claimsset.&lt;/li&gt;
&lt;li&gt;combineJWTHeader_Claimset -&amp;gt;Combines the header and claimsset.&lt;/li&gt;
&lt;li&gt;signPkey-&amp;gt; Signs the Private key and returns the assertion&lt;/li&gt;
&lt;li&gt;fetchToken-&amp;gt; basically fetches the token with all the above info passed as JWT assertion.&lt;/li&gt;
&lt;li&gt;doInit-&amp;gt; calls all of the methods and performs callout by calling fetchToken. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step-1E: Test the apex code.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can try calling doInit() method from execute anonymous to check and verify if the token is being obtained(or not)&lt;br&gt;
Once you are seeing the token properly, You can quickly use postman by making a simple call to any salesforce REST API endpoint of that org to cross check if that token's working.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step-2: . Callout to ConversationEntry endpoint by passing ConversationIdentifier (VendorCallKey).&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step-2A:  The LWC Component&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I am trying to fetch the conversations on a button click. So this is the UI part of my LWC.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    &amp;lt;article class="slds-card"&amp;gt;
        &amp;lt;div class="slds-card__body slds-card__body_inner"&amp;gt;                
            &amp;lt;lightning-button variant="brand-outline" label="Fetch Conversations" title="Fetch Conversations" onclick={onclickhandler} class="slds-m-left_x-small"&amp;gt;&amp;lt;/lightning-button&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;footer class="slds-card__footer"&amp;gt;
                 &amp;lt;template for:each={conversationEntryList} for:item="conversationEntryObject"&amp;gt;
                    &amp;lt;p key={conversationEntryObject.serverReceivedTimestamp}&amp;gt;{conversationEntryObject.sender.role} said ---&amp;gt; "{conversationEntryObject.messageText}"&amp;lt;/p&amp;gt;
                &amp;lt;/template&amp;gt;
         &amp;lt;/footer&amp;gt;
        &amp;lt;/article&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Exposing this to Record Page, home page  and App  page (this can be modified as per the requirement)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;
&amp;lt;LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata"&amp;gt;
    &amp;lt;apiVersion&amp;gt;54.0&amp;lt;/apiVersion&amp;gt;
    &amp;lt;isExposed&amp;gt;true&amp;lt;/isExposed&amp;gt;
    &amp;lt;masterLabel&amp;gt;Connect API Utility Component&amp;lt;/masterLabel&amp;gt;
    &amp;lt;description&amp;gt;This is a demo component used to get conversation payload.&amp;lt;/description&amp;gt;
    &amp;lt;targets&amp;gt;
        &amp;lt;target&amp;gt;lightning__RecordPage&amp;lt;/target&amp;gt;
        &amp;lt;target&amp;gt;lightning__AppPage&amp;lt;/target&amp;gt;
        &amp;lt;target&amp;gt;lightning__HomePage&amp;lt;/target&amp;gt;
    &amp;lt;/targets&amp;gt;
    &amp;lt;targetConfigs&amp;gt;
        &amp;lt;targetConfig targets="lightning__RecordPage"&amp;gt;
            &amp;lt;objects&amp;gt;
                &amp;lt;object&amp;gt;VoiceCall&amp;lt;/object&amp;gt;
                &amp;lt;object&amp;gt;Case&amp;lt;/object&amp;gt;
            &amp;lt;/objects&amp;gt;
        &amp;lt;/targetConfig&amp;gt;
    &amp;lt;/targetConfigs&amp;gt;
&amp;lt;/LightningComponentBundle&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;*&lt;em&gt;Step-2B:  Javascript part of the LWC. *&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We are fetching the VendorCallKey field value from the current VoiceCall record page&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { LightningElement,api,wire } from 'lwc';
import { getRecord, getFieldValue } from "lightning/uiRecordApi";
import CALLSTATUS_FIELD from "@salesforce/schema/VoiceCall.CallDisposition";
import VENDORCALLKEY_FIELD from "@salesforce/schema/VoiceCall.VendorCallKey";
import fetchConversations from "@salesforce/apex/JWTUtils.fetchConversations";
import MailingPostalCode from '@salesforce/schema/Contact.MailingPostalCode';

const fields = [CALLSTATUS_FIELD,VENDORCALLKEY_FIELD];

export default class EinsteinConversationSentiment extends LightningElement {

    isCallCompleted = false;   
    conversationEntriesResponse={};
    conversationEntryList=[];
    currentCE;
    conversationEntryObjectList=[{
        role:"NA",
        message:"NA",
        servertimestamp:"NA"
    }];
    error;
    conversationMap;

    @api
  recordId;

    @wire(getRecord, {
        recordId: "$recordId",
        fields
      })
      voicecall;



      onclickhandler(e)
      {
            console.log("Vendor Call Key for this record - "+this.voicecall.data.fields.VendorCallKey.value );
        fetchConversations({ vcKey: this.voicecall.data.fields.VendorCallKey.value })
            .then(result =&amp;gt; {
                this.conversationEntriesResponse = JSON.parse(result);
                console.log(this.conversationEntriesResponse.conversationEntries);
                this.conversationEntryList = this.conversationEntriesResponse.conversationEntries;
            })
            .catch(error =&amp;gt; {
                this.error = error;
            });
      }

}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;*&lt;em&gt;Step-2C:  Calling the Connect Conversation Entries Endpoint. *&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now, the Logic to fetch the entries. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE- I have added this in the same class where I am fetching JWT token. &lt;br&gt;
Refer Step-1D git repo class.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@AuraEnabled
    public static String fetchConversations(String cid){
        // this method is responsible to fetch the JWT token. 
// stores the access token in access_token variable
        JWTUtils.doInit();
// replace your mydomain here.
        String url = String url = 'https://&amp;lt;mydomain&amp;gt;.my.salesforce.com/services/data/v53.0/connect/conversation/'+cid+'/entries';

        try {
            // Instantiate a new http object
            Http h = new Http();
            // Instantiate a new HTTP request, specify the method (GET) as well as the endpoint
            HttpRequest req = new HttpRequest();
            req.setEndpoint(url);
            req.setMethod('GET');
            req.setHeader('Authorization','Bearer '+access_token);
            // Send the request, and return a response
            HttpResponse res = h.send(req);
            System.debug(res.getBody());
            return res.getBody();
        } catch (Exception e) {
            throw new AuraHandledException(e.getMessage());
        }
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You would receive the list of ConversationEntries as a response from the conversation entries endpoint.  The below object shows one of the ConversationEntry from the List returned.&lt;/p&gt;

&lt;p&gt;In Step-2B you are parsing the response, and storing the list of conversationentries in "conversationEntryList" and if you compare this with Step-2A , you can see we are iterating over "conversationEntryList"&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;this.conversationEntryList = this.conversationEntriesResponse.conversationEntries;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;template for:each={conversationEntryList} for:item="conversationEntryObject"&amp;gt;
 &amp;lt;p key={conversationEntryObject.serverReceivedTimestamp}&amp;gt;{conversationEntryObject.sender.role} said ---&amp;gt; "{conversationEntryObject.messageText}"&amp;lt;/p&amp;gt;
 &amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each conversation Entry is stored in "conversationEntryObject"  variable and that object consists of below information.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "clientDuration": 4695,
    "clientTimestamp": 1649938471000,
    "identifier": "f7e30ac2-6666-3333-oooo-0c0811wsfb304",
    "messageText": "12, okay?",
    "relatedRecords": [
        "0LQ5j000000PuK1"
    ],
    "sender": {
        "appType": "telephony_integration",
        "role": "Agent",
        "subject": "VIRTUAL_AGENT"
    },
    "serverReceivedTimestamp": 1649938501255
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, (for this project) what we are looking here is for 2 things: &lt;/p&gt;

&lt;p&gt;-&amp;gt; Who said it ? (Is the conversation message from Agent Or End user?)-&amp;gt; "sender.role"&lt;br&gt;
-&amp;gt; What did they say ?  (The actual Message) --&amp;gt;"messageText"&lt;/p&gt;

&lt;p&gt;We are obtaining those in below way&lt;/p&gt;

&lt;p&gt;{conversationEntryObject.sender.role}&lt;br&gt;
{conversationEntryObject.messageText}&lt;/p&gt;

&lt;p&gt;Once All of these pieces are in place, You should see something like this &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1651120845145%2Fkb3SYhEP6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1651120845145%2Fkb3SYhEP6.png" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we are able to see the transcripts (the conversation of the voice call) obtained programmatically. &lt;/p&gt;

</description>
      <category>salesforce</category>
      <category>servicecloudvoice</category>
      <category>scv</category>
      <category>jwt</category>
    </item>
    <item>
      <title>OAuth 2.0 JWT Bearer Flow for Server-to-Server Integration</title>
      <dc:creator>kashyap </dc:creator>
      <pubDate>Wed, 31 Mar 2021 06:01:50 +0000</pubDate>
      <link>https://dev.to/kashyap_kalakbandi/oauth-2-0-jwt-bearer-flow-for-server-to-server-integration-2le5</link>
      <guid>https://dev.to/kashyap_kalakbandi/oauth-2-0-jwt-bearer-flow-for-server-to-server-integration-2le5</guid>
      <description>&lt;h1&gt;
  
  
  Isn't Salesforce a CRM ? Why are talking about JWT with Salesforce ?
&lt;/h1&gt;

&lt;h6&gt;
  
  
  Exactly, Salesforce is a CRM and also a solid developer friendly and completely flexible platform which supports integration with almost any of 3rd party systems , database, applications.
&lt;/h6&gt;

&lt;h2&gt;
  
  
  Hmmmm ok .. Why JWT ? There are other authorization flows which can be used.
&lt;/h2&gt;

&lt;p&gt;For other types of mainstream authorization flows such as Webserver flow, you need a user presence to authenticate.&lt;/p&gt;

&lt;p&gt;Sometimes you want to authorize servers to access data without interactively logging in each time the servers exchange information. &lt;/p&gt;

&lt;p&gt;For these cases, you can use the OAuth 2.0 JSON Web Token (JWT) bearer flow. &lt;/p&gt;

&lt;h2&gt;
  
  
  But How ?
&lt;/h2&gt;

&lt;p&gt;Well, This flow uses a certificate to sign the JWT request and doesn’t require explicit user interaction. &lt;br&gt;
However, this flow does require prior approval of the client app.&lt;/p&gt;
&lt;h3&gt;
  
  
  How does this work in a nutshell ?
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;The client(who ever is trying to access salesforce data) posts a JWT to the Salesforce OAuth token endpoint. &lt;br&gt;
Salesforce then processes the JWT, which includes a digital signature, and issues the access token(As per prior approval of app).&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  OK! Lets look into a simple example between 2 Salesforce Orgs
&lt;/h2&gt;
&lt;h4&gt;
  
  
  OrgA with a Visualforce tab acting as Client App.
&lt;/h4&gt;
&lt;h4&gt;
  
  
  OrgB acting as target salesforce server from where we need to get authorized and fetch data.
&lt;/h4&gt;

&lt;p&gt;I will refer these as OrgA and OrgB through out the post.&lt;/p&gt;

&lt;p&gt;Lets take a look into our client application (which is a visualforce page tab)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnu13ggfcbydrywxscje7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnu13ggfcbydrywxscje7.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you hit Fetch JWT Token button on that page, You should expect an access token along with other parameters issued by a our salesforce OrgB (or) as highlighted "&lt;a href="https://oceans11-dev-ed.my.salesforce.com" rel="noopener noreferrer"&gt;https://oceans11-dev-ed.my.salesforce.com&lt;/a&gt;"&lt;/p&gt;
&lt;h2&gt;
  
  
  Lets talk code now.
&lt;/h2&gt;
&lt;h4&gt;
  
  
  I will split the flow into 6 steps for simplicity.
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Create a JWT&lt;/li&gt;
&lt;li&gt;Create a Certificate and private key.&lt;/li&gt;
&lt;li&gt;Upload the Certificate in connected app of your target OrgB&lt;/li&gt;
&lt;li&gt;Upload the private key in Files of your Client OrgA&lt;/li&gt;
&lt;li&gt;Request for access token&lt;/li&gt;
&lt;li&gt;Salesforce Grants Access Token&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  1.  Create a JWT
&lt;/h3&gt;

&lt;p&gt;JWT is JSON Web Token. It consists of header and claims.&lt;br&gt;
JWT header should look like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{"alg":"RS256"}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;alg - algorithm you are using&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It firstly consists of claims, it should be of this format.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
"iss": "3MVG99OxTyEMCQ3gNp2PjkqeZKxnmAiG1xV4oHh9AKL_rSK.BoSVPGZHQ
ukXnVjzRgSuQqGn75NL7yfkQcyy7", 
"sub": "my@email.com", 
"aud": "https://login.salesforce.com", 
"exp": "1333685628"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;lets see what do we have here... These are called JWT Claims.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;iss - OAuth client_id&lt;/code&gt;&lt;br&gt;
&lt;code&gt;sub - username of the target org you are connecting to&lt;/code&gt;&lt;br&gt;
&lt;code&gt;aud - url you would want to connect. if thats a sandbox then use test instead of login.&lt;/code&gt;&lt;br&gt;
&lt;code&gt;exp - time to expire the token.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You have to Base64url encode the JWT Header and the encoded JWT Claims Set separately without any line breaks.&lt;/p&gt;

&lt;p&gt;Next, Create a string for the encoded JWT Header and the encoded JWT Claims Set in this format&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Encoded JWT Header+ "." + Encoded JWT Claims
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It would look something like this &lt;em&gt;(before the dot(.) we have the header in encoded format )&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiAiM01WRzk5T3hUeUVNQ1EzZ05wMlBqa3FlWkt4bm1BaUcxeFY0b0hoOUFLTF9yU0su
Qm9TVlBHWkhRdWtYblZqelJnU3VRcUduNzVOTDd5ZmtRY3l5NyIsICJwcm4iOiAibXlAZ1NjI4In0=
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Please refer to &lt;strong&gt;generateJsonBody&lt;/strong&gt; and &lt;strong&gt;combineJWTHeader_Claimset&lt;/strong&gt; method for the logic using apex code provided in the Git Repo link at the end of this post.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now we have the JWT claims &amp;amp; header , lets see step 2&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Create a Certificate and private key.
&lt;/h3&gt;

&lt;p&gt;This flow requires a digital certificate and the private key used to sign the certificate. &lt;/p&gt;

&lt;p&gt;Please feel free to use your own private key and certificate issued by a certification authority. &lt;/p&gt;

&lt;p&gt;Alternatively, you can use OpenSSL to create a key and a self-signed digital certificate.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_auth_key_and_cert.htm" rel="noopener noreferrer"&gt;Refer this on How to create a Digital Certificate &lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you have completed this step, &lt;/p&gt;

&lt;h3&gt;
  
  
  3. Upload the Certificate in connected app of your target OrgB
&lt;/h3&gt;

&lt;p&gt;We would need to upload this digital certificate to the connected app in OrgB that is also required for the JWT bearer authorization flow. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy25fvieh8bn5c1un0ek9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy25fvieh8bn5c1un0ek9.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Upload the private key in Files of your Client OrgA
&lt;/h3&gt;

&lt;h5&gt;
  
  
  and create the payload to access the token
&lt;/h5&gt;

&lt;p&gt;As You already have the private key file which you obtained while creating the self signed open ssl certificate, we use it  to sign the request &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Since this is a salesforce org, I have uploaded it in a File and retrieved it using the ContentVersion object.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Sign the resulting string using RSA SHA256.&lt;br&gt;
Create a string of the string from this step in the following format.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;the combined JWT string + "." + base64_encoded_signature
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;See &lt;strong&gt;retrievePKContent&lt;/strong&gt; and &lt;strong&gt;signPkey&lt;/strong&gt; method from the Git repo link which &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;the base64 encoded signature should be something like this (I have clipped the content for keeping it small).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiAiM01WRzk5T3hUeUVNQ1EzZ05wMlBqa3FlWkt4bm1BaUcxeFY0b0hoOUFLTF9yU0su
Qm9TVlBHWkhRdWtYblZqelJnU3VRcUduNzVOTDd5ZmtRY3l5NyIsICJwcm4iOiAibXlAZ1NjI4In0=.iYCthqWCQucwi35yFs-nWNgpF5NA_a46fXDTNIY8ACko6BaEtQ9E6h4Hn1l_pcwcK​
I_GlmfUO2dJDg1A610t09TeoPagJsZDm_H83bsoZUoI8LpAA1s-2a​
36y2L2Bh7M8TNWiKa_BNM6s1FNKDAwHEWQrNtAeReXgRy0MZgQY2rZtqT2FcDyjY3JVQb​
En_CSjH2WV7ZlUwsKHqGfI7hzeEvVdfOjH9NuaJozxvhPF489IgW6cntPuT2V647JWi7ng
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Request for Access Token.
&lt;/h3&gt;

&lt;p&gt;Next, Once you have the entire base64encoded string , make a callout to the token endpoint of the target org ORGB in this case.&lt;/p&gt;

&lt;p&gt;the endpoint should look like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://login.salesforce.com/services/oauth2/token?grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&amp;amp;assertion='+YOUR-ENTIRE-JWT-VALUE STRING YOU PREPARED '
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This should be a POST call. &lt;/p&gt;

&lt;h3&gt;
  
  
  6. Salesforce grants access token.
&lt;/h3&gt;

&lt;p&gt;once done, if everything is place correctly, You should see a response with access token. &lt;/p&gt;

&lt;p&gt;If we see the Visualforce page above, that gives you the below result. &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fehmj1vuqb0fvr7l5ynic.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fehmj1vuqb0fvr7l5ynic.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you observe the image, I got the access token, I can see all the scopes and the id corresponds to the user id and org id &lt;br&gt;
and the token type which is bearer.&lt;/p&gt;

&lt;p&gt;Using this token you can easily access the data of the Target OrgB&lt;/p&gt;

&lt;p&gt;Please find the complete code in &lt;a href="https://github.com/kashyapkbandi/oauthflows" rel="noopener noreferrer"&gt;GIT Link HERE&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Please do not commit any changes to main&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Hope this post helps someone who is trying to understand the JWT with salesforce or is trying to implement it. &lt;/p&gt;

&lt;p&gt;See you again with a new post.&lt;/p&gt;

</description>
      <category>salesforce</category>
      <category>authentication</category>
      <category>integration</category>
      <category>jwt</category>
    </item>
    <item>
      <title>Password Manager using LWC</title>
      <dc:creator>kashyap </dc:creator>
      <pubDate>Mon, 29 Mar 2021 07:50:36 +0000</pubDate>
      <link>https://dev.to/kashyap_kalakbandi/password-manager-using-lwc-p9l</link>
      <guid>https://dev.to/kashyap_kalakbandi/password-manager-using-lwc-p9l</guid>
      <description>&lt;p&gt;Total time taken - 28 hours (including intermittent breaks :P )&lt;/p&gt;

&lt;p&gt;This is Password manager application which can be used for internal teams to store their credentials as a Lightning App.&lt;/p&gt;

&lt;p&gt;This application performs basic functionalities of a password manager Create password records, Update them, store and delete them along with generation of random passwords and exporting them to CSV (send to current user via Email attachment).&lt;/p&gt;

&lt;p&gt;This uses Lightning message service to relay the selections made on the list to other components.&lt;/p&gt;

&lt;p&gt;Link to Git repo:&lt;br&gt;
&lt;a href="https://lnkd.in/g2YpiGm"&gt;https://lnkd.in/g2YpiGm&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The whole purpose of this application is to showcase flexibility of using LWC for various functionalities. &lt;/p&gt;

</description>
      <category>javascript</category>
      <category>lightningwebcomponents</category>
      <category>reactnative</category>
      <category>salesforcedev</category>
    </item>
  </channel>
</rss>
