Plugins are often the way in D365 to handle things like data validation as they can run synchronously and block invalid updates but for async processing and longer running processes I prefer function apps.

I have worked on implementing and maintaining function apps in production for high volumes of transactions including things such as payments (integrating with Braintree), finance (integrating with D365 Finance and Operations), other external API integrations, and core business logic. Overall I have found them to be very flexible and perform well.

They are also less subject to platform bugs that exist in Power Automate and Logic Apps. You are more self reliant.

So, how do you talk to your Function App from your D365 environment? Function Apps can be triggered by all sorts of things such as timers, files being put into your storage account etc. but the most common use case that I have encountered (and have been using) is calling them from a Power Automate cloud flow. Authentication and authorisation to actually run the cloud flow is handled by the platform, but from there you handle the request to the Function App.

How it runs:

  • Cloud flow fetches your client ID/secret/URL from an Azure Key Vault
  • Flow uses an HTTP action to call API Management (which you put your Function App behind). You use the HTTP action which natively handles Entra authentication and pass in the client ID and secret. You also pass the subscription key in the header.
  • APIM checks the roles of the OAuth token and evaluates the request. If it passes the policy, it is forwarded to the Function App
  • The Function App is behind the built in Easy Auth and also checks for the presence of the token, the function key (inserted by APIM), and the IP address of the caller being your APIM instnace
  • Work is carried out and the Function App returns the result to your caller

Mistakes I have seen and ways to leave yourself exposed:

  • Leaving the Function App without any network restrictions. It should only accept requests from APIM.
  • Relying solely on a subscription key, which if stolen, remains valid. For example if an employee was to be offboarded and had copied the subscription key, they could continue to use this after their own account had been offboarded
  • Calling functions from the client side via Javascript and revealing the subscription key. The user is already authenticated in your D365 environment, so why wouldn’t you make use of this and check the caller?

Leave a comment