Expanding the capabilities of Dynamics 365 CRM requires seamless integration with external services. Azure Functions, with their serverless architecture and diverse functionalities, offer an ideal solution. This article guides you through calling Azure Functions from Dynamics 365 CRM plugins while incorporating secure token-based authentication, ensuring enhanced security and control.
Prerequisites:
- Dynamics 365 CRM instance
- Active Azure subscription with Function App (HTTP-triggered function)
- Basic understanding of Dynamics 365 plugin development
- Azure Active Directory (AAD) app registered with Microsoft Graph API permissions
Steps:
1. Configure AAD App and Permission:
- Access the Azure portal and navigate to Azure Active Directory.
- Click “App Registrations” and register a new Web app/API application.
- Note down the Application (client) ID and Secret generated.
- Under “API permissions,” add “Microsoft Graph” and grant appropriate delegated permissions (e.g., user.read, offline_access).
- Expose an API URL to access the registered app’s permissions (e.g., <invalid URL removed>).
2. Acquire Access Token in the Plugin:
- In your Dynamics 365 plugin code, leverage the C#
XrmTooling.Connector
library to establish a connection. - Utilize the
ExecuteAsync
method of theClient
class, passing the Organization service URI and user credentials. - Construct the OAuth 2.0 authorization request URL with:
resource
parameter set to the Dynamics 365 CRM instance URL (e.g., https://your-org.crm.dynamics.com)client_id
as your AAD app’s client IDclient_secret
as your AAD app’s secretgrant_type
set toclient_credentials
- Send an HTTP POST request to the constructed URL and parse the JSON response to extract the access token.
Example (C# snippet to generate token):
public static string GenerateAccessToken()
{
try
{
string azureFunctionToken = string.Empty;
string tenantId = "Your_Tenant_ID_URL";
string clientId = "Your_Client_ID";
string clientSecret = "Your_Client_Secret";
string resource = "Your_Resource"; // Resource identifier
string grantType = "client_credentials";
// Azure AD token endpoint
var tokenEndpoint = "https://login.microsoftonline.com/" + tenantId + "/oauth2/token";
using (var webClient = new WebClient())
{
// Construct parameters for token request
var parameters = new NameValueCollection();
parameters.Add("client_id", clientId);
parameters.Add("client_secret", clientSecret);
parameters.Add("resource", resource);
parameters.Add("grant_type", grantType);
// Send token request and receive response
var responseTokenBytes = webClient.UploadValues(tokenEndpoint, "POST", parameters);
string responseTokenContent = Encoding.UTF8.GetString(responseTokenBytes).Replace(@"\", "");
// Deserialize response to access token object
var azureFunctionTokenResponse = responseTokenContent.Deserialize<AzureFunctionTokenResponseBase>();
azureFunctionToken = azureFunctionTokenResponse.access_token;
// Return the access token
return azureFunctionToken;
}
}
catch (Exception ex)
{
// Handle any exceptions
Console.WriteLine("Exception Error: " + ex.Message);
throw;
}
}
3. Call Azure Function with Token:
- In your plugin code, prepare the data you want to send to the Azure Function (e.g., serialize into JSON).
- Create an
HttpClient
object and set theAuthorization
header with the Bearer token you obtained. - Use the
HttpPostAsync
methodHttpClient
to send the data to your Azure Function’s HTTP trigger URL. - Ensure the Azure Function is configured to validate the provided token using AAD authentication and handle the received data accordingly.
Example (C# snippet to call Azure Function):
// Method to call Azure Function
public static string CallAzureFunction()
{
try
{
// Prepare request data
var req = new {};
// Azure Function endpoint URL
string requestUri = "Your_Azure_Function_URL";
// Get access token for authorization
var accessToken = AccessTokenGenerator();
// Prepare request object
HttpResponseMessage response = new HttpResponseMessage();
string serializedRequest = JsonConvert.SerializeObject(req);
var method = new HttpMethod("POST");
var requestObj = new HttpRequestMessage(method, requestUri);
// Set request headers
requestObj.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
requestObj.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
// Set request content
requestObj.Content = new StringContent(serializedRequest, Encoding.UTF8);
requestObj.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
// Send request and receive response
HttpClient httpClient = new HttpClient();
response = httpClient.SendAsync(requestObj).GetAwaiter().GetResult();
string responseText = response.Content.ReadAsStringAsync().Result;
// Return response
return responseText;
}
catch (Exception ex)
{
// Handle any exceptions
Console.WriteLine("Exception Error: " + ex.Message);
throw;
}
}
Remember:
- Store sensitive information like the AAD app secret securely using encrypted configuration options within Dynamics 365 CRM.
- Handle errors gracefully in both plugin and Azure Function code, implementing retry mechanisms if necessary.
- Consider using Managed Identity for Azure Functions for seamless token acquisition without managing secrets directly in the code.
By following these steps and adapting them to your specific requirements, you can securely call Azure Functions from Dynamics 365 CRM plugins, unlocking powerful integrations and enhancing your automation capabilities.