7

Trying to write an Apex method that accesses Chatter REST api using this technique: https://chintanblog.blogspot.com/2017/02/call-salesforce-rest-api-from-apex.html

This method is @AuraEnabled - so it can be called from a Lightning Component.

The problem is I'm getting a 401:

System.CalloutException: [{"message":"This session is not valid for use with the REST API","errorCode":"INVALID_SESSION_ID"}]

String sfdcURL = URL.getSalesforceBaseUrl().toExternalForm(); 
String restAPIURL = sfdcURL + '/services/data/v41.0/chatter/feed-elements';  

HttpRequest httpRequest = new HttpRequest();  
httpRequest.setMethod('POST');   
httpRequest.setHeader('Authorization', 'OAuth ' + UserInfo.getSessionId());        
httpRequest.setHeader('Authorization', 'Bearer ' + UserInfo.getSessionId()); 
httpRequest.setEndpoint(restAPIURL);  

httpRequest.setBody('test');

Http http = new Http();   
HttpResponse httpResponse = http.send(httpRequest);  

Can anyone tell me what I'm doing wrong?

5 Answers 5

9

The Session Id for Lightning is specifically restricted from most API calls. This means that you need to use a Named Credential to enable access to the APIs. This is outlined in the documentation.

By security policy, sessions created by Lightning components aren’t enabled for API access. This prevents even your Apex code from making API calls to Salesforce. Using a named credential for specific API calls allows you to carefully and selectively bypass this security restriction.

The restrictions on API-enabled sessions aren’t accidental. Carefully review any code that uses a named credential to ensure you’re not creating a vulnerability.

So, you need to create a Named Credential back to the Salesforce API, then use that Named Credential instead of using UserInfo.getSessionId().

2
  • Thank you. That makes sense. Let me look at this Named Credential. May 22, 2018 at 16:23
  • I created a Named Credential - but I want it to authenticate as the current user. Now I'm getting this error: You don't have permission to view this data. Ask your administrator to set up authentication for the external data source. Note that I'm trying to access Chatter REST api - in the same org, through Lightning + APEX. May 22, 2018 at 18:13
3

Follow up:

Using Named Credentials is fine - but it won't work in all cases. For instance - if I was to use Chatter, the identity used is the Named Credential authorized. This won't work.

Using a VF Page however, uses the current user's session. This seems to be what I need.

FOLLOW UP: 1-9-2019

I ran into this article which described exactly what I needed back then. It is a really good write up with great explanations, history and a references:

https://douglascayers.com/2018/09/10/calling-rest-api-from-lightning-components-without-named-credentials/

Kudos DOUGLAS C. AYERS

1

Winter 19 on words we can make API calls to own SF org from @Aura Enabled Apex Methods with out using Remote site Settings/connected App

3
  • this is still not possible. I am getting the same invalide_session_id error in v47.0 Feb 6, 2020 at 11:56
  • @SagarThoriya can you post your issue with new Question, so it's easy to give solution for your Issue.
    – sdandamud1
    Feb 6, 2020 at 14:36
  • From the doc it is still not possible. Read last paragraph
    – Eric
    Nov 8, 2020 at 0:46
0

The solution: Connected App and Named Credentials can be followed in this tutorial Calling Salesforce APIs From Lightning Components

There is also another option - which is to use a VF page. More information here: How to Call Salesforce API from Lightning Component

0

I found the simplest solution - get the session id from apex page. Here we go : Create visualforce page name SessionId. Page content :

<apex:page contentType="text/plain">
    <apex:outputText >{!$Api.Session_ID}</apex:outputText>
</apex:page>

Get session id in the lightning component controller :

private static String getApexSessionId() {
    
    PageReference reportPage = Page.SessionId;
    if (Test.isRunningTest()) {
        sessionId =UserINfo.getSessionId();
    } else {
        sessionId = reportPage.getContent().toString();
    }
    return sessionId;  
}

Work like a charm!

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .