[SalesForce] Lightning: Getting a 401 when calling @AuraEnabled Apex method to do a REST call

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?

Best Answer

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().