function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Marcel Vreuls 3Marcel Vreuls 3 

Named Credentials between two salesforce ORGS

Hi Experts, collegues

I have the following issue. we have several salesforce org's. My requirement is to read records from the lead object Org1 to a custom object in Org2. I am using the REST API and this is working fine. Credentials, API keys etc i store in custom settings.
SO basically:
- setup a connected app in ORG1
- Create some custom classes in ORG2, which call ORG 1
- Stored configuration data in custom settings.



Now you ask, what is the issue!! it is working. Well the security people do not want api, usernames etc stored in custom settings. So i found a solution on the community using an auth provider with named credentials. So the setup
- Connected app in ORG1
- Auth provider and Named credentials in ORG2
- Off course validated and authenticated.
- adjusted the custom code a bit, on the part of the endpoints.

Now it is not working anymore. I get
 -  [{"message":"This session is not valid for use with the REST API","errorCode":"INVALID_SESSION_ID"}]
- or [{"errorCode":"NOT_FOUND","message":"The requested resource does not exist"}]

So to give you some more context:

In development Console I execute:

 WebserviceHttpRest myCall = new WebserviceHttpRest();
 myCall.authenticateByUserNamePassword('key','secret','name','password', true);
 myCall.doSoqlQuery('SELECT ID,Company, Fiber__C,LG_DateOfEstablishment__c,LG_InternetCustomer__c,LG_LegalForm__c,LG_MobileCustomer__c,LG_Segment__c,LG_VisitPostalCode__c FROM lead;'); 
 
The authenticateByUserNamePassword looks like this

public void authenticateByUserNamePassword(String consumerKey, String consumerSecret, String uName, String uPassword, Boolean isSandbox) {
        // Reference documentation can be found in the REST API Guide, section: 'Understanding the Username-Password OAuth Authentication Flow' OAuth 2.0 token is obtained from endpoints:
        //  PROD orgs   : https://login.salesforce.com/services/oauth2/token
        //  SANDBOX orgs: https://test.salesforce.com/services/oauth2/token


        //Fetch inlogdata from customsettings
        IWebServiceConfig storedConfig =  WebServiceConfigLocator.getConfig('mycustomConfig') ;
        if(storedConfig == null) throw new ExMissingDataException('Invalid data set name provided');
        uName = storedConfig.getUsername();
        uPassword  = storedConfig.getPassword();

        //String uri          = 'https://' + (isSandbox ? 'test' : 'login') +  '.salesforce.com/services/oauth2/token';
        String uri          = '/services/oauth2/token';
        String clientId     = EncodingUtil.urlEncode(consumerKey,'UTF-8');   
        String clientSecret = EncodingUtil.urlEncode(consumerSecret,'UTF-8'); 
        String username     = EncodingUtil.urlEncode(uName,'UTF-8');  
        String password     = EncodingUtil.urlEncode(uPassword,'UTF-8');
 
        String body =   'grant_type=password&client_id=' + clientId + 
                        '&client_secret=' + clientSecret +
                        '&username=' + username + 
                        '&password=' + password; 
 
        HttpResponse hRes = this.send(uri,'POST',body, false);
        if (hRes.getStatusCode() != 200) 
            System.debug('[HTTP-01] OAuth 2.0 access token request error. Verify username, password, consumer key, consumer secret, isSandbox?  StatusCode=' +  hRes.getStatusCode() + ' statusMsg=' + hRes.getStatus());
            System.debug('response body =\n' + hRes.getBody());
         
 
        Map<String,String> res = (Map<String,String>) JSON.deserialize(hRes.getBody(),Map<String,String>.class);
 
        this.accessToken        = res.get('access_token');     // remember these for subsequent calls
        this.sfdcInstanceUrl    = res.get('instance_url');  
    }
 

 The send methode looks like:

     private HttpResponse send(String uri, String httpMethod, String body, Boolean contentType) {
         
        if (Limits.getCallouts() == Limits.getLimitCallouts())
            system.debug('[HTTP-00] Callout limit: ' + Limits.getCallouts() + ' reached. No more callouts permitted.');
        
        Http        h       = new Http();
        HttpRequest hRqst   = new HttpRequest();
        
        // hRqst.setEndpoint(uri );                     // caller provides, this will be a REST resource  PostMethod m = new PostMethod(url + "?_HttpMethod=PATCH");
        hRqst.setEndpoint('callout:myNamedCredential/'+ uri + '');
        system.debug('setEndpoint: callout:ZiggoOrg/' + uri);
        hRqst.setMethod(httpMethod);                // caller provides
        system.debug('setMethod: ' + httpMethod);
        hRqst.setTimeout(6000); 
        if (body != null)
            hRqst.setBody(body);                   // caller provides
               system.debug('setBody: ' + body);
        if (contentType) {
            hRqst.setHeader('Content-Type', 'application/json');
        }
        
        if (this.accessToken != null)               // REST requires using the token, once obtained for each request
            hRqst.setHeader('Authorization','Bearer ' + this.accessToken);
             system.debug('setHeader: ' + this.accessToken);
             system.debug('hRqst'+hRqst );
        return h.send(hRqst);                   // make the callout
    }  



    The setendpoint with comments is working with thew custom settings.
    

    Any ideas suggestions
E Jayaraman IyerE Jayaraman Iyer
Hi,

So, the named cred that we create has the base URL of the end point, so when we write callout:myNamedCredential, we are basically replacing this with the base url from the named credential. Here, you are apending the Base url with the URI you are forming from code, which is why I think its failing.