We are currently switching to an OAuth based authorization solution based on the @azure/msal-node
package to authorize our API's with the ones provided by Dynamics 365 Business Central (19.5, Cloud). Somehow I can not get it to work. Our tenant instance just returns a 401 when requesting any resource using the retrieved token.
Really reached a dead end here, any help would be greatly appreciated.
Permissions set in Azure's "App Registrations" section
And yes, I have consented all of those Permissions on behalf of our tenant (admin consent)
The token even contains following scopes when decoded over at jwt.ms:
{
"scopes": [
"Automation.ReadWrite.All",
"app_access",
"API.ReadWrite.All"
]
}
Example of our implementation
/**
* Uses `msal-node` to authenticate against the microsoft servers
* to gain access to Dynamics 365 Business Central
*/
async getClientCredentialsToken() {
try {
const validity = await this.validateClientCredentialsToken();
if (validity) return;
const authOptions = {
clientId: process.env.AAD_CLIENT_ID,
authority: process.env.AAD_AUTHORITY,
clientSecret: process.env.AAD_CLIENT_SECRET,
};
const cacheOptions = {
Account: {},
IdToken: {},
AccessToken: {},
RefreshToken: {},
AppMetadata: {},
};
const cca = new msal.ConfidentialClientApplication({
cache: cacheOptions,
auth: authOptions,
});
const response = await cca.acquireTokenByClientCredential({
azureRegion: null,
skipCache: true,
scopes: ["https://api.businesscentral.dynamics.com/.default"],
});
return response;
} catch (err) {
console.log(err);
}
},
Example of a response when requesting an existing endpoint
No matter what endpoint is hit. This is the response I get for it:
{
"error": {
"code": "Authentication_InvalidCredentials",
"message": "The server has rejected the client credentials. CorrelationId: b004d293-f576-40c9-bbc6-3fb32533a65b."
}
}
Solution found inside the Docs
So for anybody stumbling upon the same scenario I have found something that finally worked! You need to register the application inside the Dynamics 365 Business Central client as described inside the official documentation.