{KnowHow}–Authentication with Dynamics CRM online Web API without user login screen– Where headless authentication works and where not?
I have wrote blogs on how to execute call web-api from HTML page as well as Web Application sometime back. And while I truly appreciate the vast number of people writing back to me on how much they liked the blog, there were asks of how to acquire the access token seamlessly for Dynamics CRM Online, that is without user intervention.
For readers who are not aware of OAuth concepts and how it works in CRM perspective, please visit the below link.
The above post first gives you an introduction to the OAuth 2.0 protocol and then how to use that to connect to Dynamics CRM Web API endpoint from an external HTML Page. The post also covers on how to register the application in azure AD and get the client id and the client secret. Before you read further I would strongly suggest you go through the above post and understand how OAuth 2.0 works from CRM perspective.
So coming back to the topic, I put my head around a lot to get headless authentication from my web application but could not make it through. Basically, I was doing similar to what is mentioned in the below git-hub article, but somehow could not make it work from my web application. The git-hub mentions about the new ADAL library which introduces the classes for the headless authentication.
https://github.com/Azure-Samples/active-directory-dotnet-native-headless
By chance one of the community discussions in Dynamics CRM group of facebook was discussing on a topic similar to this, I was directed to the original article on this topic
I carefully read through the entire post and finally after reading the limitations section I could understand why it is not working for my web application, although I am able to make it work from my WPF application or a simple c# console client.
First the positive one. How to make it work for native client applications. Below is the example for the same.
As a client I chose a C# console client. I registered my client in Azure AD and allowed implicit authorization in the manifest of the application. Also I allowed my application access to my Online Microsoft CRM instance. Getting bit confused about all this. You can always go back to the first link I shared in this post and understand. All these are explained in great details.
Everything is ready. So let’s get a bit dirty here with code.
Below is the code for my application. I am just retrieving the accounts and displaying the account names. CRM instance URL is – https://xrmtr20.crm.dynamics.com
static void Main(string[] args)
{
UserCredential userCredential = new UserCredential("<office 365 user name>", "<Office 365 Password>");
string authorityUri = "https://login.windows.net/xrmtr20.onmicrosoft.com/oauth2/authorize";
TokenCache tokenCache = new TokenCache();
AuthenticationContext context = new AuthenticationContext(authorityUri);
AuthenticationResult result = context.AcquireToken("https://xrmtr20.crm.dynamics.com", "<client id obtained after registering with Azure AD>", userCredential);
LoadAccounts(result.AccessToken);
Console.Read();
}
static void LoadAccounts(string accessToken)
{
var webRequest = (HttpWebRequest)WebRequest.Create(new Uri("https://xrmtr20.crm.dynamics.com/api/data/v8.0/accounts?$select=name,address1_city&$top=10"));
webRequest.Method = "GET";
webRequest.ContentLength = 0;
webRequest.Headers.Add("Authorization", String.Format("Bearer {0}", accessToken));
webRequest.Headers.Add("OData-MaxVersion", "4.0");
webRequest.Headers.Add("OData-Version", "4.0");
webRequest.ContentType = "application/json; charset=utf-8";
using (var response = webRequest.GetResponse() as System.Net.HttpWebResponse)
{
//Get reader from response stream
using (var reader = new System.IO.StreamReader(response.GetResponseStream()))
{
string responseContent = reader.ReadToEnd();
dynamic dynamicObj = JsonConvert.DeserializeObject(responseContent);
foreach (var data in dynamicObj.value)
{
Console.WriteLine("Account: {0}", data.name.Value);
}
}
}
}
And these are the list of accounts.
Let’s explain the code a bit here. To use this code you have to add reference to Active Directory Authentication Library (ADAL) and then NewtonSoft.json.dll
In visual studio open Tools –> NuGet Package manager –> Package manage console
In the console, type the following command
Install-Package Microsoft.IdentityModel.Clients.ActiveDirectory -Version 2.7.10707.1513-rc –Pre
The package will be installed successfully. In the same way you can add reference to Newtonsoft.json.dll using the Nuget.
Once done, now its time to review the code.
The first improvement is the UserCredentials which has a provision for taking both the username and the password. The authorityuri in the code is basically the login screen of windows live to login to your dynamics crm application. If you carefully notice the URL here, it contains xrmtr20.onmicrosoft.com. This is the AD tenant you need to access to get the token.
Also the new ADAL API introduces new overloads of the AcquireToken.
public AuthenticationResult AcquireToken(string resource, string clientId, UserCredential userCredential);
public Task<AuthenticationResult> AcquireTokenAsync(string resource, string clientId, UserCredential userCredential)
I have utilized both the above to get the access token. The remaining code just passes the access token to CRM to fetch the account data. Some mundane stuff.
Oh! So far so good and it works great with native client applications like WPF based application or C# console client. Unfortunately, I was not able to make it work from my web application project. The area where I got stuck is, a web application project would need to use the client secret as well apart from the client id to get the access token and I could not find a overload of acquire token which would take the UserCredential object along with the client secret.
Just copying some of the limitations of headless authentication from one of the previous links I shared in this post. The content is as-is from the link.
Constraints & Limitations
Here there’s a list of limitations you’ll have to take into account when using this flow.
Only on .NET
Given the intended usage of this feature, we decided to add it only to .NET.
On Windows Store we added the ability to use Windows Integrated auth, which has many of the same advantages and less drawbacks. Details in another post.
No web sites/confidential clients
This is not an ADAL limitation, but an AAD setting. You can only use those flows from a native client. A confidential client, such as a web site, cannot use direct user credentials.
No MSA
Microsoft accounts that are used in the context of an AAD tenant (classic example: Azure admins) cannot authenticate to AAD via raw credentials – they MUST use the interactive flow (though the PromptBehavior.Never flag remains an option).
No MFA
Multi-factor authentication requires dynamic UX to be served on the fly – that clearly cannot happen in this flow.
No Consent
Users do not have any opportunity of providing consent if username & password are passed directly.
No multi-hop federation
Any scenario requiring home realm discovery, multiple federation hops and similar won’t work – the protocol steps are rigidly codified in the client library, with no chance for the server to dynamically influence the authentication path.
No any server side features, really
In the “traditional” AcquireToken flows you have the opportunity of injecting extra parameters that will influence the behavior of AAD – including parameters that AAD didn’t even support when the library was released. None of that is an option when using username and password directly.
I would be happy if someone can get this working for me.
Hope this helps!
This was originally posted here.

Like
Report
*This post is locked for comments