Named Credentials using OAuth 2.0

In the previous post, we implemented Named Credentials using Anonymous and Password Authentication protocol and explained the basics of Named Credentials. You can check it here. In this post, we will implement Named Credentials using the OAuth 2.0 protocol with Named Principal Identity Type to get the data from External applications. So let’s just hop into the implementation.

Implementation

In this implementation, we will create a REST Web Service in Salesforce Org which will return the list of Accounts. We will call that Web Service from another Salesforce Org to fetch the list of Accounts and display it on UI.

Named Credentials using OAuth 2.0
Named Credentials using OAuth 2.0

REST Web Service

In the target org, first, write a simple REST Web Service that will return the list of Accounts.

AccountRest.apxc

@RestResource(urlMapping='/AccountService/*')
global class AccountRest {
    
	@HttpGet
    global static list<Account> fetchAccounts(){
        return [SELECT Name, AccountNumber, Phone, Website FROM Account order by CreatedDate DESC LIMIT 10];
    }
}

Connected App

As we are using OAuth 2.0, we have to create a Connected App in the target org and enable OAuth Settings. Type App Manager in the Quick Find box and select App Manager. Click on New Connected App. Enter required fields under Basic Information. Under API (Enable OAuth Settings), check Enable OAuth Settings checkbox. For now, enter some URL in Callback URL because we have to change it later. For Selected OAuth Scopes, select Full Access and Perform requests on your behalf at any time (refresh_token, offline_access) for this demonstration. You can select it as per your business requirement. Keep the remaining fields as default and click on Save. We will get the Consumer Key and Consumer Secret. It will take 2-10 minutes to enable the Connected App. It should look something like below:

Connected App with OAuth 2.0
Connected App with OAuth 2.0

Auth. Provider

In the Source Org, first, we need to create Auth. Provider. Type Auth. Providers in Quick Find box and click on Auth. Providers. Click New and select Provider Type. In this case, we will select Salesforce. Enter Name and Url Suffix along with Consumer Key and Consumer Secret that we got earlier in the Connected App. For some of the Identity Providers, Authorize Endpoint URL and Token Endpoint URL will be used automatically by the Auth. Provider based on the Provider Type we selected. We can provide it explicitly as well based on our Provider Type. As we have selected Salesforce, leave it blank. For Default Scopes, enter refresh_token full. We have selected the same thing for our Connected App as well. Keep the rest of the fields as default and click Save. It should look something like below:

Auth. Provider in Salesforce
Auth. Provider in Salesforce

Salesforce Configuration URLs should also be created for this Auth. Provider. Copy the Callback URL and paste it in the Callback URL field for the Connected App that we created earlier.

Named Credentials using OAuth 2.0

Finally, we have to create a Named Credentials in source org. Follow the same steps mentioned in the earlier post to create a Named Credentials. Enter the endpoint of our Rest Web Service in the URL field. This time, select Identity Type as Named Principal. A Named Principal applies the same credential or authentication configuration for the entire org, while Per User authentication provides access control at the individual user level. We will use Per User later in this post. For the Authentication Protocol, select OAuth 2.0 and for the Authentication Provider, select the Auth. Provider we just created earlier. Keep the Scope field blank as it will override the scopes that we mentioned in the Auth. Provider. Check Start Authentication Flow on Save checkbox which will start the Authentication flow once we hit the Save button. keep the Generate Authorization Header checkbox checked and hit Save.

It will start the Authentication flow. You will be redirected to the Login page for the target org. Enter the Credentials of target org. It will ask permission to access your data based on the Scopes we entered in the Connected App. Click Allow and you will be redirected to the Named Credentials page. In the Authentication Status field, it should show that Authenticated as <some username>.

OAuth Flow using Named Credentials
OAuth Flow using Named Credentials

Now we just need to call this Web Service from Apex using Named Credentials. Provide the Named Credentials in Endpoint and HTTP Method for the HTTPRequest and that is enough. Named Credentials will take care of passing the headers for Authentication. As we have provided refresh_token in the Scopes, it will also create the refresh token automatically once it is expired.

AccountManager.apxc

public class AccountManager {
    
    @AuraEnabled
    public static list<Account> fetchAccounts(){
        Http http = new Http();
        HttpRequest request = new HttpRequest();
        request.setEndpoint('callout:AccountCreds/apexrest/AccountService');
        request.setMethod('GET');        
        HttpResponse response = http.send(request);
        if (response.getStatusCode() == 200) {
            list<Account> results = (list<Account>) JSON.deserialize(response.getBody(), list<Account>.class);
            return results;
        } else {
            System.debug('### ' +response.getBody());
        }
		return null;
    }
}

Create simple Lightning Component to call the apex method and display list of Accounts using Datatable.

AccountManager.cmp

<aura:component controller="AccountManager" implements="flexipage:availableForAllPageTypes">
    <!-- attributes -->
    <aura:attribute name="data" type="Object"/>
    <aura:attribute name="columns" type="List"/>
    <lightning:card title="Named Credentials - OAuth 2.0 Implementation">
        <div class="slds-p-left_x-small">
            <lightning:button label="Get Accounts from External System" onclick="{!c.getAccounts}" /> <br/><br/>
        
            <div style="height:315px">
                <lightning:datatable keyField="id" data="{!v.data }" columns="{!v.columns }"
                        hideCheckboxColumn="true"/>
            </div>
        </div>
    </lightning:card>
</aura:component>

AccountManagerController.js

({
    getAccounts: function (component, event, helper) {
        helper.getAccountsHelper(component, event, helper);
    }
});

AccountManagerHelper.js

({
	getAccountsHelper : function(component, event, helper) {
		var action = component.get("c.fetchAccounts");
        action.setCallback(this, function(response) {
            var state = response.getState();
            if (state === "SUCCESS") {
                
                // Set the columns for Datatable
                component.set('v.columns', [
                    {label: 'Name', fieldName: 'Name', type: 'texts'},
                    {label: 'Account Number', fieldName: 'AccountNumber', type: 'text'},
                    {label: 'Phone', fieldName: 'Phone', type: 'phone', 
                        cellAttributes: { iconName: 'utility:phone_portrait' }},
                    {label: 'Website', fieldName: 'Website', type: 'url'}
                ]);
                
                component.set("v.data", response.getReturnValue());
            }
            else {
                console.log("Failed with state: " + state);
            }
        });
        $A.enqueueAction(action);
	}
})

This is how we can implement a Named Credentials using OAuth 2.0 with Named Principal Identity Type.

Per User Identity Type

In this implementation, we used Identity Type as Named Principal. Once we authenticate, it will use the same credentials for the entire org and all users can use these Named Credentials to call the External System. As this post is already long, I will cover the Identity Type as Per User in the next post. This will allow individual users to maintain their credentials for External System. The individual user has to authenticate themselves before accessing the External System.

Check this official Salesforce documentation to know more about Named Credentials.

Please Subscribe if you don’t want to miss new posts. I will see you in the next post. Cheers till then.

1 thought on “Named Credentials using OAuth 2.0”

  1. Great post, it helped us a lot setting this up!

    Is it also possible to use this in a single org, for the following scenario?
    – A Flow calls an Apex invocable (User A1 with Profile B1)
    – The Apex invocable starts a Queueable
    – The Queueable makes a callout, to the current org, with a Named Credential
    – The named credential is authorized with User A2 with Profile B2
    – The named credential is linked to an Auth.Provider
    – The Auth.Provider is linked to a Connected App (with Profiles B1 and B2)

    We’re currently receiving: [Status=Unauthorized, StatusCode=401] (for both Users)
    But having no idea how to solve this, if possible.

    Can this be done?

    Reply

Leave a Comment