401. Unauthorized error while querying Dynamics 365 Web Api from external application. Follow these steps to avoid the error

Follow my blog for more interesting topics on Dynamics 365, Portals and Power Platform. For training and consulting, write to us at info@xrmforyou.com


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

image
  • Enter the necessary information. Name is anything you wish to give. Sign-on Url is my website’s sign-on page.
image
  • Once the application is created then note down the Application ID and then click on Settings. You Application ID here is the Client ID.
image
  • Click on Required Permissions –> API’s –> Select an API and choose – Dynamics CRM Online
image
  • Choose Delegated permissions as highlighted below and the save your settings in Azure.
image
  • Then click on Keys. Enter the key name to get a key value. Copy it immediately and store it. It is your client secret.
image

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.
image
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”.
image
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.
image
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 – webappuser@xrmforyou53.onmicrosoft.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.

 

Debajit Dutta
(Dynamics MVP)
For consultation/ training visit www.xrmforyou.com or reach out to us at info@xrmforyou.com

8 thoughts on “401. Unauthorized error while querying Dynamics 365 Web Api from external application. Follow these steps to avoid the error”

  1. Thank you for the in-depth explanation! I am working on hitting a Survey API that was a breeze on-prem, but giving me fits after we migrated. Error was simply ‘One or more errors occurred’ LOL! Thanks a lot Microsoft! Anyway, this looks like the key to get to where I need to be. Keep you posted, and thank you so much for sharing your hard-earned knowledge. Takes a special kind of person to do what you’re doing, and I, for one, really appreciate it.

    1. Hi Jesse
      Thanks for reading my blog. I understand your pain and for many of my customers who prefer to stay on-premise for their own reasons. Somehow this online first approach may not fit all customers..But thats the way it it is…
      Yes it does take some effort but again its comments like yours that help me keep going…thanks.
      Cheers!
      Debajit Dutta

  2. Hi ,
    I have followed same process but getting error 401(unauthorized) while accessing CRM API.
    Can you please explain in detail about application user?
    I created it from CRM and assigned application id but still facing same issue.

    1. Did u give the application user appropriate security role in CRM which is required to perform whatever Web API operation you are trying to execute?

  3. HI Debajit, AZURE AD token system changed by Microsoft …can you please update the article.

    1. Hi Sairam,
      Thanks for reading my blog. Can you help me which part of the stuff written in blog has been changed recently. Are you referring to the new App registration page in Azure portal with new look and feel.
      I have my customers who are still running fine with this method. Appreciate your inputs here.
      Cheers!
      Debajit

  4. Great Article it help to me access the MS CRM data Without Authentication, Please Update Article new changes are came into AZURE AD

Comments are closed.