There are two main ways to main ways to perform Server-to-Server (S2S) authentication: with a client id/client secret or with certificates. People most commonly use the client secret option as it is much easier to implement -- you create a new secret on the App Registration and you can use it. However, certificate-based authentication is generally considered to be more secure than using a client secret (which is effectively just a password). It seems that most people shy away from using certificates for authentication because of the perceived complexity in using them.

In this blog, I'll show that it is actually very easy to maintain self-signed certificates in an Azure Key Vault and use them to connect to Dynamics 365 through an Azure Function -- all with minimal configuration and code.

Configuration

In order to wire this up, we need to configure a few resources in Azure and Dynamics 365.

Azure Key Vault

This is where we will create and store the self-signed certificate. Alternatively, you could import a certificate you previously generated.

  1. Create a new Key Vault resource in Azure.
  2. Go to Certificates > Generate/Import
    • Set the Certificate Name
    • Set the Subject (can be anything)
    • Click Create
      • Azure Key Vault - Create Certificate
  3. After the certificate has generated, export it
    • Download in CER format
      • Azure Key Vault - Export Certificate
    • Copy the Secret Identifier from the bottom of the page.

Azure Active Directory

We need to register a new application in Azure AD and configure the certificate on it. This is the application that our Azure Function will use to get a valid OAuth access token which is authorized to access Dynamics 365.

  1. Go to Azure Active Directory > App Registrations
  2. Click New Registration
    • Give it a Name, you can leave the Redirect URI blank
  3. Copy the Application (client) ID value
  4. Click on Certificates & secrets
    • Upload the .cer file you downloaded above
      • Azure AD - Upload Certificate

Dynamics 365

Next, we need to configure an Application User in Dynamics 365. This user is mapped to the Azure AD App Registration, and it is granted a security role which controls what the user can access.  For more details on this, check out this link.

  1. Go to Settings > Security > Users
  2. Switch the view to Application Users
  3. Create a new User
    • Switch to the Application User form
    • Populate the Application ID with the Application ID from the App Registration
  4. Assign a security role to the user

Azure Function

Finally, we deploy the Azure Function which will use the certificate from the Key Vault to connect to our Dynamics 365 environment. The Azure Function uses a system

  1. Deploy the Azure Function
    • See the next section for the code
  2. Go to Platform Features > Identity
    • Turn the System Assigned identity to On
      • Azure Function - Managed Identity
  3. Go back to the Azure Key Vault.
    • Click on Access Policies > Add New
    • Select the principal that matches the managed identity of the Azure Function (should have the same name)
    • Grant it "Get" access for "Secret permissions"
    • Click OK
      • Azure Key Vault - Access Policies
  4. Go back to the Azure Function
  5. Open the Configuration/Application Settings
  6. Set the "Certificate" application setting, replacing URI with the Secret Identifier you copied above.
    • @Microsoft.KeyVault(SecretUri=https://bguidinger.vault.azure.net/secrets/CertificateName/VersionNumber)
    • Azure Function - App Settings

Development

The code for the Azure Function can be found here.

As you can see, the Function code is very simple -- we don't need to wire up any code to pull the certificate from the Azure Key Vault. Instead, we we just pull the configuration values from the App Settings...which includes the Certificate setting value (which is the Base64 encoded certificate with the public and private key).

var certificateString = ConfigurationManager.AppSettings["Certificate"];
var certificateBytes = Convert.FromBase64String(certificateString);
var certificate = new X509Certificate2(certificateBytes, string.Empty, X509KeyStorageFlags.MachineKeySet);

Once we have the X509Certificate2 object, we can use it with the CrmServiceClient. Note that the second and third parameters (certificate store/thumbprint) are not required since we are directly passing the certificate in.

var client = new CrmServiceClient(certificate, StoreName.My, null, instanceUri, true, null, clientId, null, null);

Once we have the CrmServiceClient, we can check the IsReady parameter to make sure we connected successfully. If it's true then we're connected to CRM!

Testing

All that's left to do now is test the Function! To do this, we can open up Postman and execute an HTTP GET request to the Function URL (since it's an HTTP Triggered function).

Postman - Test

So there you have it. An Azure Function that connects to Dynamics 365 using certificate-based authentication with minimal configuration and code! In the next blog, I'll show how, if you're using an App Service, you can use an Azure Managed Identity (both system-assigned and user-assigned) to make connecting to Dynamics 365 even easier.

References

  1. Use OAuth with Common Data Service - Connect as an app

  2. Use Key Vault references for App Service and Azure Functions