In my previous Salesforce series we learned how to perform authentication, login, run queries, and create, update, or delete records using the Salesforce SOAP API. In this new series we're going to work through similar tasks using the Salesforce REST API because not every technology stack, or development team, is willing and able to handle SOAP requests.
Today we're going to set up our application's connection to Salesforce, including the creation of our Connected App, and use our application to login through the Salesforce REST API. All of my code examples will be from a C# .NET Core application, but will work in .NET Framework as well, and my Salesforce examples will be using Lightning Experience (Spring 2020 release).
Connected App
The first step to integrating with the Salesforce REST API is creating a new Connected App within your Salesforce org. I recommend doing this in Test or Development first, before releasing your app into Production! This app will serve as the endpoint your application uses to authenticate with your Salesforce org and allows an admin to grant or restrict permissions for apps' access to data as well as users' access to external apps.
- Navigate to Setup > Apps > App Manager.
- Click "New Connected App".
- Fill in the required information on the New Connected App form using whatever Connected App Name you'd like, a real Contact Email, and a Callback URL. The Callback URL can be a dummy URL as we will be using the 'resource owner password grant' - in other words our application will authenticate with Salesforce using a legitimate user's Username and Password. Check Enable OAuth Settings and select "Access and manage your data (api)" under Selected OAuth Scopes.
- Click Save and then click Continue. Take note of your Consumer Key and Consumer Secret. These cannot be revealed again and are essential for your application to access your org.
- As per the warning, don't use the app for several minutes after creation.
Authenticating From .NET
Next we need to create or modify our .NET application and create a few properties to store our login, authentication, and client info:
public const string LoginEndpoint = "https://test.salesforce.com/services/oauth2/token";
public const string ApiEndpoint = "/services/data/v36.0/"; //Use your org's version number
private string Username { get; set; }
private string Password { get; set; }
private string Token { get; set; }
private string ClientId { get; set; }
private string ClientSecret { get; set; }
public string AuthToken { get; set; }
public string ServiceUrl { get; set; }
static readonly HttpClient Client;
static MyController()
{
Client = new HttpClient();
}
The above getters and setters contain confidential information. These should be stored using a secure method for retrieval during authentication.
We will build our authentication to the API using the HttpClient class for our asynchronous HTTP callouts, and FormUrlEncodedContent which is required by Salesforce. This can also be done synchronously if you choose by using the Result keyword on any async calls. If you are returned a bad request response, double check that you've used FormUrlEncodedContent correctly.
Note: If you run into a security error, add the TLS 1.1 or 1.2 protocols to your method or constructor and try to send the request again:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11;
HttpContent content = new FormUrlEncodedContent(new Dictionary<string, string>
{
{"grant_type", "password"},
{"client_id", ClientId},
{"client_secret", ClientSecret},
{"username", Username},
{"password", Password}
});
HttpResponseMessage message = Client.PostAsync(LoginEndpoint, content).Result;
string response = message.Content.ReadAsStringAsync().Result;
JObject obj = JObject.Parse(response);
AuthToken = (string)obj["access_token"];
ServiceUrl = (string)obj["instance_url"];
Testing our method by printing the result of the response should return the following JSON object containing our authentication token as a string:
"{
\"access_token\":\"00D630000004mdS!AR0AQHhG_MsU_i5BqeqvimbRa.BP4Oanqn4v9UUedHDk_.BCP6p4dDPnnhZ7Y8nhtra1v2DWuPUOwt.IaDlj_XdnCYLgzIDd\",
\"instance_url\":\"https://cs43.salesforce.com\",
\"id\":\"https://test.salesforce.com/id/00D630000004mdSEAQ/00560000003gFPbAAM\",
\"token_type\":\"Bearer\",
\"issued_at\":\"1588270529868\",
\"signature\":\"XFhjeOi/xxL+PoNW7kW1vhp1cgus9OT16fhoFEBEKfs=\"
}"
// These values have been modified for security
If you run into an invalid_client_id error, go to Settings and view the Profile for the account you're using to log in. Verify that the new Connected App you've created is checked under Connected App Access.
The access_token and instance_url values are used to set our AuthToken and ServiceUrl respectively. We will access these values later when we perform queries, create new records, and update existing records.
In the next post of this series we will use our new authentication token to perform a query and retrieve an Account from our Salesforce org.
If you'd like to catch up with me on social media, come find me over on Twitter or LinkedIn and say hello!