I have wrote quite a few articles over the last one year to query Dynamics Web API using ADAL from client side and as well as server side. However lately I am receiving loads of queries on how to Authenticate with web-API without using any user credential or how to authenticate with new Server to Server (S2S) authentication.
I thought of providing some good links already available there. However I feel that some of the steps mentioned are not pictorially represented. Hence penning down this blog for the benefit of my blog readers.
In this example I will give a complete example of querying the list of account through Web API from a External web app and not just getting the bearer token.
There are two steps to this example
1. Get the token Authorization token from Azure
2. Send the authorization token to get the list of accounts from CRM using the Web API endpoint.
Step 1: Register your application with Azure to get the Client ID and Client Secret
- Enter the necessary information. Name is anything you wish to give. Sign-on Url is my website’s sign-on page.
- Once the application is created then note down the Application ID and then click on Settings. You Application ID here is the Client ID.
- Click on Required Permissions –> API’s –> Select an API and choose – Dynamics CRM Online
- Choose Delegated permissions as highlighted below and the save your settings in Azure.
- Then click on Keys. Enter the key name to get a key value. Copy it immediately and store it. It is your client secret.
Step 2: Use ADAL in your Code to get the bearer token
The next step is to get the bearer token. To do this, open your project and through Nu-get package manager, add reference to the latest version of ADAL.
Below is the code to get the bearer token. Please read the comments to make the code work for your organization.
ClientCredential credential = new ClientCredential("<replace with your client id>", "<replace with your client secret>");
string authorityUri = "https://login.microsoftonline.com/xrmforyou53.onmicrosoft.com/oauth2/authorize"; // here xrmforyou53.onmicrosoft.com is my crm domain. Please replace with your domain
TokenCache tokenCache = new TokenCache();
AuthenticationContext context = new AuthenticationContext(authorityUri);
AuthenticationResult result = await context.AcquireTokenAsync("https://xrmforyou53.crm.dynamics.com", credential); // https://xrmforyou53.crm.dynamics.com is my CRM URL. You need to use your crm url to test this.
var authToken = result.AccessToken;
Please observe, we have not used the credentials of any user anywhere.
Step 3: Get the accounts from CRM.
So far you may be thinking that this is what we have already tried before as well. What’s new in this.
Well I take the below piece of code and try to load my account list.
public async Task LoadAccount(string bearerToken)
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", bearerToken);
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; //
var result = httpClient.GetAsync("https://xrmforyou53.crm.dynamics.com/api/data/v9.0/accounts?$select=name").Result;
var accountJSON = await result.Content.ReadAsStringAsync();
However I receive 401. Unauthorized error.
If you are feeling now it’s time to learn something new, you are right. But before we go ahead, let’s understand why you are getting unauthorized error. After all, in Azure I gave the app to access Dynamics as a Organization user.
That step enabled the client application to access Dynamics CRM by using the Application ID and the client secret. Your client application is now able to be authenticated against Azure AD with permission to access CRM Online. However, CRM Online does not know about this "client application" or "user". CRM API will response a 401 if you try to access it.
So let’s jump to step 4.
Step 4: Create an Application User in CRM and assign security roles to it.
Well this may be a previous step but I deliberately put it in the last one to make you understand the unauthorized error.
Go to CRM –> Security –> Users and switch the view from the default view to “Application Users”.
Click on the New button to create a New Application User. You may be landing to the user form by default. Change the form to application user form.
In the application ID, enter the application ID of your app you obtained from Azure in Step 1.
I put the name of the user as – WebApp Application User
Email I put as – email@example.com. I have used my domain. You better use your CRM domain. The name will automatically populate from the email you give. Once you save the record, CRM will auto populate the Application ID URI and the Azure AD Object ID.
Now in this example we are trying to retrieve account records. So it’s better you create a custom security role and assign to this user which will give the application user read permission on the Account record. I copied the Salesperson role and then assigned to this application user. Basically whatever operation you want to perform using Web API, you need to provide the same privilege to the application user.
Now when you run the code in Step 3, this time you get the account JSON. The icing on the cake is Application user won’t consume CRM licenses as well.
Hope this was helpful for you guys.
For consultation/ training visit www.xrmforyou.com or reach out to us at firstname.lastname@example.org