[SalesForce] How to use JsForce in a Salesforce Lightning Component

BACKGROUND

I would like to be able to interact with the various Salesforce REST API from client-side JavaScript code, without needing to go via a Apex controller method and then making a separate Apex callout.

I have created a POC component:

Component

<aura:component controller="JavaScriptForceController" implements="flexipage:availableForAllPageTypes">
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
    <ltng:require scripts="{!$Resource.jsforce + '/jsforce.min.js'}" />
</aura:component>

JavaScript Controller

({
    doInit : function(cmp, event, helper) {

        helper.callAction(cmp, 'c.getSessionID', null, function(sessionId){
            console.log(sessionId) 

            let params = {};
            params.sessionId = sessionId;
            params.serverUrl = 'https://xxx-dev-ed.lightning.force.com';
            params.instanceUrl = 'https://xxx-dev-ed.lightning.force.com';
            params.logLevel = 'DEBUG';
            params.version = '43.0';

            var conn = new jsforce.Connection(params);
            conn.sobject("Account").describe(function(err, meta) {

                if (err) return console.error(err); 

                console.log('Label : ' + meta.label);
                console.log('Num of Fields : ' + meta.fields.length);

                meta.fields.forEach(function(field) {
                    console.log(field.name + ' - '  + field.label + ' - ' + field.type);
                });
            });
        });
    }
})

Apex Controller

public class JavaScriptForceController {

    @AuraEnabled
    public static String getSessionID(){

        return UserInfo.getSessionID();

    }
}

And a JavaScript Helper

({
    callAction : function(cmp, methodName, params, callback){
        var self = this;
        var action = cmp.get(methodName); 
        if (params != null) action.setParams(params);
        action.setCallback(this, function(response) {
            var state = response.getState();
            console.log(methodName + ' ' + state);
            if(cmp.isValid() && state === "SUCCESS"){
                var result = response.getReturnValue();
                console.log(result);
                if (callback) callback(result);
            } else if (state === "ERROR"){
                console.log(response.getError());
            }
        });

        $A.getCallback(function() {
            $A.enqueueAction(action); 
        })();  
    },
})

CSP Trusted Sites Definition

Add a rule: https://xxx-dev-ed.my.salesforce.com

Cross-origin resource sharing (CORS).

Add rules:

  1. https://xxx-dev-ed.lightning.force.com
  2. https://xxx-dev-ed.my.salesforce.com

QUESTIONS

  1. Why do I still get these errors (see below)?
  2. Is it even possible to even use JsForce in Lightning?
  3. If not, are there any other JavaScript librarys I could use to easily interact with the Salesforce REST APIs?

method=GET,
url=/services/data/v43.0/sobjects/Account/describe GET
https://xxx-dev-ed.my.salesforce.com/services/data/v43.0/sobjects/Account/describe
401 (Unauthorized)

JsForce_Test:1 Failed to load
https://xxx-dev-ed.my.salesforce.com/services/data/v43.0/sobjects/Account/describe:
No 'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'https://xxx-dev-ed.lightning.force.com' is
therefore not allowed access.

The response had HTTP status code 401.

jsforce.min.js:3 elappsed time : 168msec jsforce.min.js:3
status=400, url=/services/data/v43.0/sobjects/Account/describe

Cross-Origin Read Blocking (CORB) blocked cross-origin response
https://xxx-dev-ed.my.salesforce.com/services/data/v43.0/sobjects/Account/describe
with MIME type application/json.

JavaScriptForce.js:24 Error: Access Declined

Reference

Best Answer

Why do I still get these errors (see below)?

You've got two things working against you: CORB and Lightning Session Id. First, CORB is a new security feature that prevents certain types of resources from being returned to the client. As far as I can tell, you can't circumvent this at all. Second, the Lightning Session Id does not have API access, so you'd have to hit the server at least once to get a compatible Session ID anyways. Overall, whatever you're attempting to do will not work well in Lightning. You should be able to do this in Visualforce, because it has an API-capable session Id and doesn't have to go across domains. The original error would have been INVALID_SESSION_ID (so you got a 401), but it was filtered out by CORB, so all your script sees is the secondary error.

Is it even possible to even use JsForce in Lightning?

Absolutely not. CORB will block all responses, because there's no API endpoint mapped to lightning.force.com. This is a browser-based security feature.

If not, are there any other JavaScript librarys I could use to easily interact with the Salesforce REST APIs?

Because of all the security restrictions, you simply won't be able to do this. There was a "hack" you could do in the past (grabbing a Visualforce Session Id), but it won't work any longer. You will necessarily need Visualforce if you want any sort of API access.

Related Topic