This is the third post in a series in which I explore integration scenarios for Business Central and Dataverse, and take a dive into possible errors and ways the integration can fail. Two previous posts here and here were focused on Dataverse solutions and how misusing the solutions can lead to integration errors. This episode is dedicated to the configuration of user permission and the ways incorrect or missing security settings can break the data synchronisation.
The first and most common issue is quite simple, with an error message providing sufficient information on the nature of the problem. Although it can look a bit scary.
An error occurred when communicating with Dataverse.
Business Central Integration Business Central to Common Data Service is missing prv_Readcronus_ProductCertificate priviledge ... for entity cronus_productcertificate.
The error message, stripped from all the service information, is simply saying that the user does not have necessary permissions to read the table cronus_productcertificate.
If you take the sample code for the blog series from my repository and simply run it without any additional permission configuration, this error is the first thing you will see in the job queue log, the reason being that integration tasks are executed under a dedicated user account in Dataverse. This account's settings include privileges for BaseApp entities, but obviously don't extend to custom tables. Custom entities must be added to the integration user security group.
One way to fix this is to find the Advanced settings under the cogwheel menu in top right corner of the Power Apps portal and use this interface for the security configuration.
From the advanced settings, we can navigate to the Security screen and configure the necessary permissions. But the whole advanced settings interface is the legacy experience, which is being deprecated. Any time soon we won't find this configuration in its familiar place anymore.
The more up-to-date and recommended method of configuring the user permissions is to do it via the environment settings.
To access the environment settings, use the same cogwheel icon to open the Admin center (it's the very first option in the drop-down menu). In the admin center, choose the environment where the app is deployed and open its settings using one of the two Settings actions highlighted in green below. There are a few settings buttons here. One in red in the navigation pane will take you to the tenant settings instead of the environment, so don't confuse them.
In the Settings screen, unfold the Users + permissions section and find the Security roles link under it. Here, you will see a long list of roles configured in the environment. It's really long, so it may be a good idea to use the search bar to filter the list to only entries containing "Business Central" in their name.
Filtered list looks more comprehensible - there are only four entries here. One that we are interested in is Business Central Dataverse Integration. Click on the role name, and it will take you to the list of database tables that can be assigned to the role. By default the list shows only tables that are already assigned to the role, so our Product Certificate is not here. To see all tables, change the filter at the top of the list from Show only assigned tables to Show all tables and once again, use the search bar to locate the custom table.
Select the table and assign the Read and (for bi-directional synchronisation) Write permissions.
After setting things up, we can return to BC and run the synchronisation again - this time without errors.
Dataverse column security
Another permissions-related error may look much more mysterious, especially for BC developers who are not familiar with the Dataverse/CE security model.
Let's assume we tested our integration code, and it works perfectly on the dev environment. But once it is deployed on the staging or production environment, we see something going wrong. One (or maybe a few) of the fields on the BC side appears to be empty, whilst all the rest look perfectly fine.
We check everything on the Dataverse side, and looks good - all values are in place, but disappear somewhere halfway to Business Central. Here in my example, the Item No. field comes blank, although the respective Dataverse field Product Number has a value.
When we delve deep into the integration code armed with the debugger, we can end up digging as deep as the CRM Integration Table Synch. codeunit, where we find out that indeed the Product Number field comes blank in the source table, although all other values are there.
It's not a weird connector bug, it seems. But how could that happen if we clearly see the product number in the Dataverse table? Moreover, this is a mandatory column in Dataverse - it simply cannot be blank.
The secret is hidden in the Dataverse security model, which is quite different from that of Business Central. Dataverse inherited from Microsoft CRM a concept called column security profiles, which allows to limit access to certain fields instead of the whole table.
You can find some more information on Microsoft Learn if you want to know more about the column-level security.
What matters for the BC integration is that the column security, when enabled, can cause the effect which we just observed in the integration code. Likely, in this situation the integration user is missing permissions to access one column in the Dataverse table.
First of all, let's make sure that the column security is actually the cause of the issue. Open the solution, edit the table Product Certificate, and open the properties of the field Product Number. Here, under the Advanced options, find the Enable column security property.
The column-level security for the product number is enabled, which means that the users require a special permission to access it. If this permission is missing, the column will show a blank value. Code accessing the column will not error out, but will receive an empty value - exactly as in the integration example above.
To give the integration user permissions to read the restricted column, start from the admin center, follow to the Environments page, and under Users + permissions, select the Column security profiles link.
Here you can see all configured security profiles, and the list is missing an important profile - one for the Business Central integration user. Which means we need to create one. Click on the New Profile and give the new profile a name (for example, Business Central Integration).
When done, click on the new profile's name. The new screen that opens shows the plain list of all the fields which have the column security enabled. By default, all the fields have all permissions set to Not Allowed.
Find the Product Number column (search bar can be very helpful again) and open its properties.
Update and Create permissions are not applicable in this case because Product Number is a calculated column. Its value is not stored in the Product Certificate table and therefore cannot be edited. Set the Read permission to Allowed and save the changes.
Once the column profile is configured, there is one last step left - the profile must be assigned to a user account or a team. Setting the security on the team level is preferred over configuring access per user. Both Teams and Users tabs are located next to the Column permissions in the security profile.
If you want to assign the security profile directly to the user, choose the Users tab, click Add Users, and find the integration user account with a complicated name Business Central Integration Business Central to Common Data Service. Yes, all the nine words!
There is no default team that the integration user belongs to, so if you want to make the assignment on the team level instead, you need to create one first. I will leave this exercise to the readers, though, but will give one hint. If you want to create a team, start from the environment settings once again.
And now the configuration is done. All synchronised records are complete, no more missing fields.