Background
I would like to connect to the REST API of a production org, from a sandbox org.
Configuration so far:
- Production Org has a
Connected App - Sandbox Org has a
Auth. Provider - Sandbox Org has a
Named Credential - Apex code in the Sandbox org uses the
Named Credentialto access the Production Org REST API
1. Production Org - Connected App
- Connected App Name:
Sandbox Enable OAuth Settingsis ticked- Callback URL:
https://x--x.cs83.my.salesforce.com/services/authcallback/Salesforce_REST_APIwhich is the sandbox - Selected OAuth Scopes:
full refresh_token Require Secret for Web Server Flowis ticked.- Noted the
KeyandSecretfor use later in the sandboxAuth. Provider
2. Sandbox Org - Auth. Provider
- Provider Type:
Salesforce - Name:
Salesforce Production REST API - URL Suffix:
Salesforce_REST_API Consumer Keyset to the key from the Production Org Connected AppConsumer Secretset to the Secret from the Production Org Connected AppAuthorize Endpoint URLused the default valuehttps://test.salesforce.com/services/oauth2/authorizeToken Endpoint URLuses the default valuehttps://test.salesforce.com/services/oauth2/token
3. Sandbox Org - Named Credential
- Label:
Salesforce Production REST API - Name:
Salesforce_Production_REST_API - URL:
https://xx.my.salesforce.comwhich is the production org url - Identity Type:
Named Principle - Authentication Protocol:
OAuth 2.0 - Authentication Provider:
Salesforce Production REST APIfrom step 2 - Scope:
full refresh_token Start Authentication Flow on Saveis tickedGenerate Authorization Headeris tickedAllow Merge Fields in HTTP Headeris ticked
Saving starts the OAuth process, and I successfully authenticate with my sandbox login details.
4. Apex code in the Sandbox org uses the Named Credential
The below code is called from a Lightning component which is running inside a publicly available community page.
public with sharing class ReportApi { private final static String REPORTS_RESOURCE = '/services/data/v44.0/analytics/reports/'; private static HttpResponse get(String reportID) { HttpRequest request = new HttpRequest(); request.setMethod(HttpMethod.GET); request.setEndpoint('callout:Salesforce_Production_REST_API' + REPORTS_RESOURCE + reportID); request.setTimeout(120000); // 2 Minutes request.setHeader('Accept', 'application/json'); request.setHeader('Content-Type', 'application/json'); request.setHeader('Authorization','OAuth {!$Credential.OAuthToken}'); HttpResponse httpResponse = new Http().send(request); return httpResponse; } } Usage
HttpResponse response = ReportApi.get(reportId); Yet I get this response from the production REST API:
{"message":"Session expired or invalid","errorCode":"INVALID_SESSION_ID"}
When I debug the HttpRequest I get this:
System.HttpRequest[Endpoint=callout:Salesforce_Production_REST_API/services/data/v44.0/analytics/reports/00O0O00000AYR0JUAX, Method=GET]
When I debug the HttpResponse I get this:
System.HttpResponse[Status=Unauthorized, StatusCode=401]
Question
- What is wrong with the above configuration?
- How should I configure the two orgs, to allow the Sandbox Org to access the Production Org's REST API?