I am new to SalesForce and am working through getting up to speed with the basics as we will be beginning a large integration project next week. For at least part of our integration we will need to access the SalesForce Rest API. To that end another gentleman on my team and I have done some basic prototyping of calls using Postman with good success, in particular around OAuth2 authentication. Our problem is that while everything seems to work fine in Postman, as soon as we switch to using C# to make the calls we begin getting an error instead of our auth token. The response is HTTP Status 400 Bad Request and the content of the response is
{"error":"invalid_grant","error_description":"authentication failure"}.
Here is a sample of some of the C# code we have tried:
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Web;
namespace SFTokenTest
{
internal class Program
{
private const string LoginUrl = "https://test.salesforce.com/services/oauth2/token";
private static void Main(string[] args)
{
FormUrlEncodedContent content = new FormUrlEncodedContent(new []
{
new KeyValuePair<string, string>("grant_type",HttpUtility.UrlEncode("password")),
new KeyValuePair<string, string>("password",HttpUtility.UrlEncode("PASSWORD")),
new KeyValuePair<string, string>("username", HttpUtility.UrlEncode("USERNAME")),
new KeyValuePair<string, string>("client_id",HttpUtility.UrlEncode("CLIENTID")),
new KeyValuePair<string, string>("client_secret",HttpUtility.UrlEncode("CLIENTSECRET"))
});
HttpResponseMessage response;
using (HttpClient client = new HttpClient())
{
response = client.PostAsync(LoginUrl, content).Result;
}
Console.WriteLine(response.Content.ReadAsStringAsync().Result);
Console.WriteLine(response.StatusCode);
Console.ReadLine();
}
}
}
Note: this is one of many implementations we have tried including using HttpWebRequest and WebClient, all with the same result.
In addition to our own code we have tried pulling code from the GitHub repository developerforce/Force.com-Toolkit-for-NET which also presented the same issue.
So far we are two days into troubleshooting this with no luck and we have stumped our SalesForce consultant as to why it is not working. We tried resetting the Security Token this afternoon to no avail as well. I have looked through a number of articles online (including on StackOverflow) most of which point to the following issues:
It seems there is something that Postman is doing that we are not in our requests, but I cannot seem to pinpoint what it is. We even captured requests from both Postman and one of our clients and diffed them and they came back as identical.
Any help would be greatly appreciated.
If you haven't solved this yet, I think this might be your issue. So according to this: https://help.salesforce.com/apex/HTViewSolution?id=000221207 Starting from June 2016 Salesforce will is disabling TLS 1.0 encryption accross its whole platform in a phased approach.
If you are on any version prior to .net 4.6, it means that you won't have TLS 1.1/1,2 switched on by default. There is a little list here of options you can use to enable it: https://help.salesforce.com/apex/HTViewSolution?id=000221207#Inboundintegrations
For a console application like yours, just tested on my side and the following worked for me (on .net 4.5.2):
string LoginUrl = "https://login.salesforce.com/services/oauth2/token";
//the line below enables TLS1.1 and TLS1.2
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
FormUrlEncodedContent content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("grant_type", "password"),
new KeyValuePair<string, string>("client_id","CLIENTID"),
new KeyValuePair<string, string>("client_secret","CLIENTSECRET"),
new KeyValuePair<string, string>("password","PASSWORD + SECURITYTOKEN"),
new KeyValuePair<string, string>("username", "USERNAME")
});
HttpResponseMessage response;
using (HttpClient client = new HttpClient())
{
response = client.PostAsync(LoginUrl, content).Result;
}
Console.WriteLine(response.Content.ReadAsStringAsync().Result);
Console.WriteLine(response.StatusCode);
Console.ReadLine();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With