Neo
Neo

Reputation: 16239

(400) Bad Request : Get AccessToken of Salesforce error:"invalid_grant"

I'm using azure function with below code - everything is working fine when i run azure fucntion locally but after deployment i'm getting below error

{"error":"invalid_grant","error_description":"authentication failure"}

Function code -

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.SystemDefault | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
                HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "tokenURL");
                var keyValues = new List<KeyValuePair<string, string>>();
                keyValues.Add(new KeyValuePair<string, string>("grant_type", "password"));
                keyValues.Add(new KeyValuePair<string, string>("client_id", "clientID"));
                keyValues.Add(new KeyValuePair<string, string>("client_secret", "clientSecret"));
                keyValues.Add(new KeyValuePair<string, string>("username", "userName"));
                keyValues.Add(new KeyValuePair<string, string>("password", "password"));

                request.Content = new FormUrlEncodedContent(keyValues);
                request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
                HttpResponseMessage response = await httpClient.SendAsync(request);

                    string respContent = await response.Content.ReadAsStringAsync();
                    var oauthResponse = JsonConvert.DeserializeObject<Dictionary<string, string>>(respContent);
                    string token = oauthResponse["access_token"];

Is there any other setting required from salesforce ?

Modify the Connected app: (Edit Policies) Relax IP restrictions

Permitted Usersto "All users may self-authorize"

Upvotes: 1

Views: 2187

Answers (1)

Sai Puli
Sai Puli

Reputation: 971

Here is what we have in our Azure Functions that is working as expected. ISalesforceConfigSettings is not from any library, its our own hand written interface whose implementation(s) read values from Environment variables.

    /// <summary>
    /// Gets the Salesforce access token given the client_id, secret, username and password.
    /// </summary>
    /// <param name="log">Tracewriter log</param>
    /// <param name="_settings">ISalesforceConfigSettings _settings</param>
    /// <returns>A Salesforce access token</returns>
    private async string GetSalesforceAccessToken(TraceWriter log, ISalesforceConfigSettings _settings)
    {
        var httpClient = new HttpClient();

        ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls12;

        // Create Request Body
        var formContent = new FormUrlEncodedContent(new[]
        {
            new KeyValuePair<string, string>("client_id", _settings.SalesforceClientId),
            new KeyValuePair<string, string>("client_secret", _settings.SalesforceClientSecret),
            new KeyValuePair<string, string>("username", _settings.SalesforceUserName),
            new KeyValuePair<string, string>("password", _settings.SalesforcePassword),
            new KeyValuePair<string, string>("grant_type", _settings.SalesforceGrantType)
        });

        try
        {
            // Call to get access token
            var loginResponse = await httpClient.PostAsync(_settings.SalesforceLoginUrl, formContent);
            var loginResponseString = await loginResponse.Content.ReadAsStringAsync();

            // Log Login Response
            log.Info(loginResponseString);

            // Extract Access Token
           return JsonConvert
                .DeserializeObject<SalesforceLoginResponse>(loginResponseString)
                .AccessToken;
        }
        catch (Exception ex)
        {
            log.Error(ex.Message);
            throw;
        }
    }

Just in case if you're wondering what is SalesforceLoginResponse class is...

using Newtonsoft.Json;

namespace Models.Salesforce
{
    public class SalesforceLoginResponse
    {
        [JsonProperty("access_token")]
        public string AccessToken { get; set; }
    }
}

Upvotes: 2

Related Questions