0

I'm attempting to gain access to Business Central Admin Center API, but I'm having some difficulties.

I'm having the idea that it has something to do with the app registration that I have made in the Azure Portal.

I have (as an admin user of the tenant) registered and app and given it "delegated permissions" to "Dynamics 365 Business Central" with access to "Financials.ReadWrite.All". I have also created a secret for the app.

My problem is that when I try to access the Admin Center API, I get a "403 Forbidden" response, so I assume that I have either forgotten something, I have created my app registration wrong somehow or that my attempt to access the API, is performed in an inaccurate manor.

If I try to examine the token I get, it doesn't show the permissions that I would expect and have seen in other cases (like with MS Graph API), so I'm thinking maybe it's the token that is the problem.

Here is the code that I use to retrieve a token and my attempt to use it afterwards - maybe someone can spot what I'm doing wrong.

Getting the token

var client_id = "removed_for_security_reasons";
var client_secret = "removed_for_security_reasons";
var tenant_id = "removed_for_security_reasons";

var token_url = "https://login.microsoftonline.com/" + tenant_id + "/oauth2/v2.0/token";

var client = new HttpClient();

var content = new StringContent(
    "grant_type=client_credentials"+
    "&scope=https://api.businesscentral.dynamics.com/.default"+
    "&client_id="+ HttpUtility.UrlEncode(client_id) +
    "&client_secret="+ HttpUtility.UrlEncode(client_secret));

content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/x-www-form-urlencoded");

var response = await client.PostAsync(token_url, content); 

// here i print the token so I can check it with jwt.io.

Attempting to use the token

var client = new HttpClient();

HttpRequestMessage req = new HttpRequestMessage();

req.Method = HttpMethod.Get;

req.RequestUri = new Uri("https://api.businesscentral.dynamics.com/admin/v2.11/applications/businesscentral/environments");
req.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue(
                "Bearer", access_token);

var res = await client.SendAsync(req);

// this results in "403 Forbidden"

There is no further information given as to why this is forbidden, so I'm having a hard time pin pointing what the problem is.

Does anyone have suggestions?

UPDATE 1

OK, so I have tried to follow the description linked. It doesn't describe which permissions box to check though and it's also using PowerShell which I'm not - I'm using C# with HttpClient.

So, to not circle around this any further, please try to explain which to select here (see images) and/or what is wrong/missing.

Image 1 (the app), what is wrong/missing:

enter image description here

Image 2 (permissions 1), what is wrong/missing:

enter image description here

Image 3 (permissions 2), what is wrong/missing: (admin grant doesn't seem to change anything)

enter image description here

After this, I create a client secret and use the code posted initially. Of cause this isn't working as expected. If the code is wrong, then please point out what the problem is - referring to the description on the web doesn't help me, as it is vague at best.

Aidal
  • 799
  • 4
  • 8
  • 33

1 Answers1

0

I think the issue is your combination of delegated permissions and trying to use the client credential flow.

Client credential flow requires application permissions which is also why your delegated permissions are not shown in your token. The client credential flow does not grant you the delegated permissions.

Even though it doesn't seem to be stated directly anywhere that Admin Center API doesn't support client credential flow, I think it is implied in the documentation.

In Using Service-to-Service (S2S) Authentication the Admin Center API is not mentioned in the Feature availability matrix and The Business Central Admin Center API does not mention client credential flow at all and all the example are using user impersonation.


Your App Registration looks okay to me. You will however need to provide the admin consent.

As described in the article I linked above you need to use MSAL (Microsoft Authentication Library). Since you are using C# you need to use MSAL.NET.

I am not an expert on C#, but maybe this quickstart guide could lead you in the right direction.

kaspermoerch
  • 16,127
  • 4
  • 44
  • 67
  • I was told by someone else in here, that delegated permissions is a must for this API. Unless I misunderstood that. I started out with application permissions. – Aidal May 03 '22 at 11:45
  • If I switch to application permissions, the Finacials.ReadWrite.All permission isn't available. I can however select API.ReadWrite.All and if I do that and get a token, this permission is also shown in jwt.io - the response from next request is still 403 Forbidden. – Aidal May 03 '22 at 11:54
  • Yes, that was me. The fact that the permissions are in the token after switching to application permissions just proves my point. You have to use delegated permissions and you cannot use `grant_type=client_credentials`. – kaspermoerch May 03 '22 at 12:48
  • Hehe OK, I'm much more interested in hearing what I should be using instead ;) – Aidal May 04 '22 at 07:10
  • Well, of course. The gist of it is that working with the Admin Center API requires user impersonation as described in "The Business Central Admin Center API" link above. It can be done without prompting the user, but that would require a user that does not have MFA activated. – kaspermoerch May 04 '22 at 07:40
  • The user I'm trying to gain access with is an admin user and does not have MFA activated. Getting where I want to go, seems to be more complex than it should be, please see my post update 1. – Aidal May 04 '22 at 09:41
  • Still nobody out there who can explain to me, how I "should" be doing this, more than how I "shouldn't" be doing this? - because the latter is well established by now. – Aidal May 12 '22 at 07:34
  • Please see my update above. – kaspermoerch May 12 '22 at 09:03
  • I followed that article and created the sample, which works for MS Graph. I still don't know how to make it work for BC Admin Center API though. Using the article approach I can get a token that does contain the permissions I have added, but here it stops. MS Graph has it's own specific client, so the sample can't be transferred directly. – Aidal May 16 '22 at 13:23
  • If you get a token with the correct permissions, then just use that token for authentication on the BC Admin Center API. It shouldn't matter which method you used to retrieve the token as long as it is valid and has the correct permissions. – kaspermoerch May 18 '22 at 07:49