I am attempting to write a connect app that will receive a set of data from an external source and put it inside an instance of microsoft dynamics 365 business central via its APIs. Documentation says there are two ways to do this, using basic authentication and logging in via Azure Active Directory. The former is easy and straightforward to do programmatically, but the documentation makes it very clear that it is not meant for production environments. I'm capable of doing the latter using Postman, but part of the process involves me typing in credentials in a popup window. Since the use case for the final product will be to run without user interaction, this won't do. I want the application to handle the credentials of what will be a service account by itself.
I'm able to modify records using basic authentication, and active directory if I fill out the login form when prompted. I've tried using a library called ADAL, but passing my account's credentials that way led to the following response: {"error":"invalid_request","error_description":"AADSTS90014: The request body must contain the following parameter: 'client_secret or client_assertion.} I have access to the client secret, but there seems to be no means of passing it via ADAL, that I've found.
I've also tried, at a colleague's recommendation, to log in using the client id and client secret as username and password. The following code is what we ended up with:
RestClient client = new RestClient("https://login.windows.net/[my tenant domain]/oauth2/token?resource=https://api.businesscentral.dynamics.com");
var request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
request.AddParameter("undefined", "grant_type=%20client_credentials&client_id=%20[my client id]&client_secret=[my client secret]&resource=[my resource]", ParameterType.RequestBody);
string bearerToken = "";
try
{
bearerToken = JsonConvert.DeserializeObject<Dictionary<string, string>>(client.Execute(request).Content)["access_token"];
Console.WriteLine(bearerToken);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
The code above successfully retrieves a token, but if I use that token I get the following response:
<error xmlns="http://docs.oasis-open.org/odata/ns/metadata"><code>Unauthorized</code><message>The credentials provided are incorrect</message></error>