David Robertson
Apr 4 · 7 min read

Introduction

The goal of this blog post is to inform you about the benefits of application users, an approach of authenticating and interacting with Dynamics 365 online for your application/s without requiring a licensed user account. This approach is particularly useful for larger projects where you exceed the 5 non interactive user accounts.

This approach becomes more beneficial as Microsoft has recently announced a new API threshold — in the article it states:

“We limit the number of API requests made by each user, per organization instance, within a five minute sliding window. “

According to the error message the new limit is “Number of requests exceeded the limit of 4000, measured over time window of 300 seconds.”

The application user might allow you to better segment your application\s and handle load(further testing required) without reaching this limitation.Note this should not be used by normal users as these accounts are not supposed to access the UI.

Non-interactive user account

First thing to look at is something called a non-interactive user account:

According to Microsoft

“It is used for programmatic access to and from Dynamics 365 for Customer Engagement apps between applications. A non-interactive user account lets these applications or tools, such as a Dynamics 365 for Customer Engagement apps to ERP connector, authenticate and access Dynamics 365 for Customer Engagement apps (online), without requiring a Dynamics 365 for Customer Engagement apps (online) license. For each instance of Dynamics 365 for Customer Engagement apps (online), you can create up to five non-interactive user accounts.”

More information on this can be found here: https://docs.microsoft.com/en-us/dynamics365/customer-engagement/admin/create-users-assign-online-security-roles#create-a-non-interactive-user-account

The downside to (non-interactive user accounts) is you are limited to 5 per instance.

Application user

The 5 limitation of service user accounts can be too limiting, you can use application user licences, Microsoft describe as:

“Introduced in December 2016 Update for Dynamics 365 (online), you can use server-to-server (S2S) authentication to securely and seamlessly communicate with December 2016 update for Dynamics 365 (online) with your web applications and services. S2S authentication is the common way that apps registered on Microsoft AppSource use to access the Dynamics 365 (online), version 8.2 data of their subscribers. All operations performed by your application or service using S2S will be performed as the application user you provide rather than as the user who is accessing your application.

All application users are created with a non-interactive user account, however they are not counted towards the five non-interactive user accounts limit. In addition, there is no limit on how many application users you can create in an instance.”

More info on this can be found here: https://docs.microsoft.com/en-us/dynamics365/customer-engagement/admin/create-users-assign-online-security-roles#create-an-application-user

So great there is a way of authenticating and accessing Dynamics 365 data that:

· Does not require a license

· You can create as many of these application accounts as you like

· If you want an app to share a user account as they have the same permission requirements you can give them each their own security key which can have its own expiry date or can be revoked as required

· For each application you can give least possible permissions to do what is required (IE the app can have its own user account and security role which only has access permissions required to do its job)

How do we set this up?

1. Follow these steps by Microsoft to Register a Dynamics 365 for Customer Engagement app with Azure Active Director https://docs.microsoft.com/en-us/dynamics365/customer-engagement/developer/walkthrough-register-dynamics-365-app-azure-active-directory and take note of the “Application ID” of the application you just created

2. Follow the instructions here for creating a security key for the app you registered the step before and note down the generated “security key” https://docs.microsoft.com/en-us/azure/active-directory/develop/howto-create-service-principal-portal#get-application-id-and-authentication-key

3. On your Dynamics 365 instance you want this to access go to Settings > Security > Users

4. On the view selector, select “Application Users”

5. Select “New”

6. On the create new user form, if not already selected change the form used to “User:application user”

7. Create the new user

a. User Name: give it a username

b. Application ID: this will be the application id of the Azure app you registered and took note of earlier

c. Full Name: give it a full name

d. Primary Email: give it an email address

8. After the user is created, like normal user accounts it will need to be given a security role, this can be either one of the out of box security roles or my recommendation is to create a security role that just has the permissions required for the app to function as required.

Code example using an application account

I will show you the method of authentication using the Dynamics 365 web API and a C# console app: Note, this uses “Microsoft.IdentityModel.Clients.ActiveDirectory” which I added via NuGet

using System;using System.Threading.Tasks;using System.Net.Http;using System.Net.Http.Headers;using Microsoft.IdentityModel.Clients.ActiveDirectory;namespace ConnectToDynamics365CE{class Program{static void Main(string[] args){//enter in the url for your Dynamics 365 online instance below, for the way i’ve coded it make sure it ends with “.com/” also you will probably want to store this as a variable (not in the code) rather than hard coding these in for deployment automation purposesstring D365URL = “https://yourinstance.crm11.dynamics.com/";//this will be the query you will be submiting to the API, for the instance defined by the URL above for example purposes I am just querying top 3 contactsstring query = “contacts?$top=3”;//create a string for your applicationID and Secret key you will probably want to store this as a variable (not in the code) rather than hard coding these in for security and deployment automation purposesstring applicationId = “applicationID”;string secret = “Secretkey”;// create a string which calls the Dynamics 365 api using the above variables and stores the response: you don’t need to store it as as a string you could deserialise the response json to an object ectstring D365response = QueryDynamics365API(D365URL, query, applicationId, secret).Result;// this is just writing out the response body either to prove it works or give you an indication of why it failedConsole.WriteLine(D365response);}public static async Task<string> QueryDynamics365API(string D365URL, string query, string applicationId, string secret){// this is taking the Dynamics 365 URL and adding the API url bitsstring api = D365URL + “api/data/v9.1/”;//This thing I found is quite cool, you send a request to get the authorisation URL from the Dynamcs 365 instance API you want to connect to, although it does have an issue which I will explain in next commentAuthenticationParameters ap = await AuthenticationParameters.CreateFromResourceUrlAsync(new Uri(api));//The ADAL (Azure Active Directory Authentication Libraries) this uses (V4) is much stricter in regards to authentication url you can use, the request to get the auth url done just before returns the url with “/oauth2/authorize”appended which if you send a request for a access token using v4 with this appended it will return an error, hence the below line of code removing “/oauth2/authorize” from the urlap.Authority = ap.Authority.Replace(“/oauth2/authorize”, “”);//creates Client credentials using the applicationId and SecretClientCredential creds = new ClientCredential(applicationId, secret);// Authenticate the registered application with Azure Active Directory.AuthenticationContext authContext = new AuthenticationContext(ap.Authority);AuthenticationResult authResult = await authContext.AcquireTokenAsync(ap.Resource, creds);//stores the token from the authResultstring token = authResult.AccessToken;// instantiating the request status and giving default value, this will change if request succeeds. only used for demo purposesstring requestStatus = “error: “;// creates a new http client to send api requestusing (HttpClient httpClient = new HttpClient()){//adds authorisation using the token generated earlierhttpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(“Bearer”, token);//awaits for response from the HTTP requestHttpResponseMessage response = await httpClient.GetAsync(api + query);//if the response is a successif (response.IsSuccessStatusCode){//I’m just setting the request status to success, this can be changed per your requirements such as deserialising into a object ectrequestStatus = “success =”;}//this is returing the request status text + the content of the request responsereturn requestStatus + await response.Content.ReadAsStringAsync();}}}}

Conclusion

After using application accounts, any application I build that needs to interact with Dynamics 365 this will be my first choice. Software vendors who provide applications which integrate with Dynamics 365 should consider providing this way of authenticating for their application. This decrease the total cost of ownership of their software as it would not require a Dynamics 365 license for the application whilst possibly making it more secure.

Image from here

Capgemini Microsoft team

To share best practices, knowledge and experiences of the Capgemini Microsoft team

David Robertson

Written by

Capgemini Microsoft team

To share best practices, knowledge and experiences of the Capgemini Microsoft team

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade