[SalesForce] Calling REST API from Apex results in “Session expired or invalid” error

I have some Apex code that tries to create a dummy class in the org. When I call the "create Apex class" method, the request's response is:

{"message":"Session expired or invalid","errorCode":"INVALID_SESSION_ID"}

I run the following snippet in Apex anonymous:

SalesforceAPI api = new SalesforceAPI();
api.createApexClass();

Here is the class:

public with sharing class SalesforceAPI
{
    final String endpoint = 'https://ap2.salesforce.com/services/data/v28.0/tooling/sobjects';

    // SomeValues to be store
    public String oid ;
    public String cid ;
    public String apmid ;
    public String carid ;

    public SalesforceAPI(){
    }


    // used receive response by sending a http request
    private String getResponse(HttpRequest req)
    {
        try
        {
            Http
            httpreq = new Http();
            HttpResponse
            res = httpreq.send(req);
            String reqresponse = res.getBody();
            return
            reqresponse;
        }
        catch (Exception e){return
        'Error:' +e.getMessage();}
    }

    // create a http request with required endpoint and request method
    private HttpRequest createHttpRequest(String endpoint, String method)
    {
        HttpRequest req = new
        HttpRequest();
        endpoint += '';
        req.setEndpoint(endpoint);
        req.setHeader('Authorization', 'OAuth ' + UserInfo.getSessionID());
        req.setHeader('Content-Type', 'application/json');
        req.setMethod(method);
        System.debug('Request: ' + req.getHeader('Authorization'));
        return req;
    }

    public void createApexClass(){
        // create a Http request with post method
        HttpRequest req = createHttpRequest(endpoint+'/ApexClass','POST');
        //req.setBody( '{"Name":"NewApexClass1","Body":"public class NewApexClass1 {}"}');
        // send request and receive response
        String response = getResponse(req);
        System.debug('RESPONSE: ' + response);
        // These two lines have no role in creating apex class. So they can be ignored for now.
        //Map<String,Object> rmp = (Map<String,Object>)JSON.deserializeuntyped(response);
        //oid = (String)rmp.get('id');
    }
}

The UserInfo.getSessionId() method is returning an id (it is not blank or null).

I have also tried running the code with and without the following Session Settings enabled:

'Lock sessions to the IP address from which they originated'

'Lock sessions to the domain in which they were first used'

'Enforce login IP ranges on every request'

Any information on what might be causing this problem or how I can go about troubleshooting it would be helpful.

Best Answer

A couple of things to check:

  1. Verify that the session is valid on ap2. If not, modify the endpoint subdomain as required.

  2. Check the Login History page on the target org. It might show additional details about the invalid session id.


Try something like the following that does work from anonymous Apex in my dev org:

HttpRequest req = new HttpRequest();
string endpointUrl = System.URL.getSalesforceBaseURL().toExternalForm() + '/services/data/v37.0/tooling';
System.debug(endpointUrl);
req.setEndpoint(endpointUrl);
req.setHeader('Authorization', 'OAuth ' + UserInfo.getSessionID());
req.setHeader('Content-Type', 'application/json');
req.setMethod('GET');

Http httpreq = new Http();
HttpResponse res = httpreq.send(req);
System.debug(res.getBody());