I am researching how the Business Central API Permission at application level works in AzureAD/EntraID.
I want my application to access high level and sensitive data in Business Central without a signed-in user.
To do so, I required the admin to grant access to my application registered in EntraID:
Then I created a console app in .NET and try to call Business Central on behalf of the registered application in Azure. I assume to list all environments in Business Central.
static async Task Main(string[] args)
{
const string clientID = "<Client ID from Azure AD>";
const string authority = "https://login.microsoftonline.com/<Tenant ID>/v2.0";
const string clientSecret = "Secret Value";
string[] scopes = new string[] { "https://api.businesscentral.dynamics.com/.default" };
var clientApp = ConfidentialClientApplicationBuilder.Create(clientID)
.WithClientSecret(clientSecret)
.WithAuthority(new Uri(authority))
.Build();
try
{
var result = await clientApp.AcquireTokenForClient(scopes).ExecuteAsync();
string accessToken = result.AccessToken;
Console.WriteLine(accessToken);
await RequestToBusinessCentral(accessToken);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
static async Task RequestToBusinessCentral(string accessToken)
{
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
string apiEndpoint = "https://api.businesscentral.dynamics.com/v2.0/admin/environments";
string apiEndpoint = "https://api.businesscentral.dynamics.com/v2.0/</sandbox/api/v1.0/companies
var response = await httpClient.GetAsync(apiEndpoint);
if (response.IsSuccessStatusCode)
{
var data = await response.Content.ReadAsStringAsync();
Console.WriteLine("Response: ");
Console.WriteLine(data);
}
else
{
Console.WriteLine($"Error in HTTP Status: {response.StatusCode});
}
}
However, I am getting errors of either 400 Bad Request or 401 Unahthorized.
Decoding the JWT token:
{
"aud": "https://api.businesscentral.dynamics.com",
"iss": "https://sts.windows.net/<Tenant ID>/",
"iat": 1710865738,
"nbf": 1710865738,
"exp": 1710869638,
"appid": "Client ID",
"appidacr": "1",
"idp": "https://sts.windows.net/<Tenant ID>/",
"idtyp": "app",
"oid": "Object ID",
"roles": [
"Automation.ReadWrite.All",
"app_access",
"AdminCenter.ReadWrite.All",
"API.ReadWrite.All"
],
"tid": "<Tenant ID>",
"ver": "1.0"
}
The access token seems good.
I follow Microsoft Documentation to set up.
I tried different API endpoints, but the results are same. Either Bad Request or Unauthorized.
In Business Central, I registered the application in Microsoft Entra Applications card. And assign the Super (Data) permission to this application.
I am looking for some clues that possibly causes such issues, I am thinking it might be in Incorrect API endpoint? Incorrect Configuration in AzureAD/EntraID? or Incorrect Configuration in Business Central?

Super (Data) permission set allows to read all tables and nothing else. But BC API endpoints are technically pages, so these requests require permissions to execute respective pages at least. Besides, API pages often invoke code from other application objects which also must be allowed by the permission set. 400 or 401 response is very likely due to missing permissions in Business Central, not a token issue. To start troubleshooting, you can also assign
D365 APIpermission set to your application:D365 APIV2 permission set
This is basically the analogue of the SUPER user permission and should not be used in production, but it's a good starting point to rule out possible OAuth token problems and start narrowing down the required permission set.
There is a trick in assigning these permission set though. It is non-assignable and cannot be selected directly from the application permissions page. If you want to set it in the application, create a custom permission set and select
D365 APIV2as include permission set. This will give your app the super user access.Besides, check the response body - it usually contains quite detailed information about the specific AL object that caused the error, likely this will be helpful in troubleshooting.