Question
When trying to call Salesforce REST API endpoints, such as /services/data/v32.0/analytics/reports
, from a Lightning Component, you may encounter issues with Content Security Policy (CSP). This typically results in an error like:
Refused to connect to 'https://na15.salesforce.com/services/data/v32.0/analytics/reports' because it violates the following Content Security Policy directive: "connect-src 'self'".
This error occurs because Lightning Components enforce CSP, which restricts direct API calls from JavaScript. Here’s a step-by-step explanation of the issue and solutions.
Your code retrieves the session ID via an Apex method (UserInfo.getSessionId()
), then uses it in an AJAX call to authenticate the REST API request. The relevant part of your code is:
var action = component.get("c.getSessionId");
action.setCallback(this, function(a) {
var sessionId = a.getReturnValue();
console.log(sessionId);
$j.ajax("/services/data/v32.0/analytics/reports", {
beforeSend: function(xhr) {
xhr.setRequestHeader("Authorization", "Bearer " + sessionId);
},
success: function(response) {
alert('success!');
},
error: function(jqXHR, textStatus, errorThrown) {
alert(jqXHR.status + "," + textStatus + ": " + errorThrown);
}
});
});
$A.enqueueAction(action);
Despite being valid when tested via tools like Postman, the request fails in Lightning due to the connect-src 'self'
directive in the CSP. This restricts calls to Salesforce API endpoints even if they are hosted within the same domain.
Answer
To overcome this limitation, you should call the REST API through Apex. This approach avoids CSP restrictions while leveraging Salesforce’s server-side capabilities for secure communication.
Solution 1: Using Apex to Handle the API Call
Apex Controller (YourController.cls
)
public with sharing class YourController {
@AuraEnabled
public static String callAnalyticsAPI() {
Http http = new Http();
HttpRequest request = new HttpRequest();
request.setEndpoint(URL.getSalesforceBaseUrl().toExternalForm() + '/services/data/v32.0/analytics/reports');
request.setMethod('GET');
request.setHeader('Authorization', 'Bearer ' + UserInfo.getSessionId());
HttpResponse response = http.send(request);
if (response.getStatusCode() == 200) {
return response.getBody();
} else {
throw new AuraHandledException('Error: ' + response.getStatus());
}
}
}
This Apex code defines a method callAnalyticsAPI
to make a REST API call to the /analytics/reports
endpoint. It constructs an HttpRequest
with the appropriate endpoint and sets the Authorization header using the session ID. The method executes the request using Http
and returns the response body if the call is successful. In case of an error, it throws an exception with the error details.
Client-Side JavaScript (YourComponentHelper.js
)
callAnalyticsAPI: function(component, event, helper) {
var action = component.get("c.callAnalyticsAPI");
action.setCallback(this, function(response) {
var state = response.getState();
if (state === "SUCCESS") {
console.log("API Response: ", response.getReturnValue());
} else {
console.error("Error calling API: ", response.getError());
}
});
$A.enqueueAction(action);
}
This client-side helper method calls the callAnalyticsAPI
Apex method and handles the response. It checks the callback state for “SUCCESS” to process the API response and logs it to the console. If an error occurs, it logs the error details to the console for debugging. This ensures smooth communication between the client-side Lightning Component and the server-side Apex logic.
Solution 2: Using a Visualforce Page to Retrieve Session ID
Visualforce Page
<apex:page>
Start_Of_Session_Id{!$Api.Session_ID}End_Of_Session_Id
</apex:page>
This Visualforce page uses the $Api.Session_ID
global variable to expose the current user’s session ID. The session ID is enclosed between custom markers, “Start_Of_Session_Id” and “End_Of_Session_Id,” to simplify parsing. This page provides a quick way to retrieve the session ID for further use.
Apex Helper Method to Retrieve Session ID
public static String getSessionIdFromVFPage() {
PageReference vfPage = Page.YourVisualforcePageName;
String content = vfPage.getContent().toString();
Integer startIdx = content.indexOf('Start_Of_Session_Id') + 'Start_Of_Session_Id'.length();
Integer endIdx = content.indexOf('End_Of_Session_Id');
return content.substring(startIdx, endIdx);
}
This Apex helper method retrieves the session ID by fetching the content of the Visualforce page created earlier. It extracts the session ID string using the defined markers and returns it. While functional, this approach has performance and security limitations and should be used cautiously.
Summing Up
When calling Salesforce REST API endpoints from Lightning Components, such as /services/data/v32.0/analytics/reports
, the Content Security Policy (CSP) restricts direct API calls from JavaScript, resulting in errors like "connect-src 'self'"
.
To overcome this, the best practice is to delegate the API call to Apex. This ensures secure communication and avoids CSP restrictions. The Apex method constructs the HTTP request, sets the Authorization header with the session ID, and processes the response. The Lightning Component calls this Apex method and handles the response in the client-side controller or helper.
Alternatively, you can retrieve the session ID using a Visualforce page with the $Api.Session_ID
global variable and pass it to your component. However, this approach is less secure and not recommended for production scenarios.
Delegating API calls to Apex is the most secure and efficient solution for this use case.
Kick Start Your Journey with Salesforce Learning
Our Salesforce Course offers a deep dive into the Salesforce platform, giving you the skills necessary for success in the CRM field. The program covers key areas such as Salesforce Admin, Developer, and AI, integrating both theoretical learning and practical experience. You will gain hands-on experience through live projects and assignments, preparing you to address complex business challenges with Salesforce solutions. Our expert instructors ensure that you acquire the practical skills and industry knowledge to excel in the Salesforce environment.
In addition to technical training, our Salesforce training in Mumbai provides personalized mentorship, exam preparation guidance, and interview readiness to help you stand out in the competitive job market. You will have access to detailed study resources, real-world project exposure, and individualized support throughout your journey. By the end of the course, you will not only be prepared for certification exams but also equipped with the experience and problem-solving skills employers are looking for. Begin your Salesforce career with us and unlock a world of career opportunities!