Getting Access Tokens for Dynamics 365 CE

Summary

Below I’ve listed the various grant types that can be used to access Dynamics 365 Web API.

More details on OAuth and the Common Data Service can be found here: https://docs.microsoft.com/en-us/powerapps/developer/common-data-service/authenticate-oauth.

Grant Type – Password

 private static bool GetAccessToken()
        {
            using (HttpClient client = new HttpClient())
            {
                client.BaseAddress = new Uri("https://login.microsoftonline.com/common/oauth2/token");

                string clientid = ""; // Azure App Registration
                string url = ""; // Org URL, e.g. https://tessla010.crm11.dynamics.com/
                string username = ""; // Your Username
                string password = ""; // Your password

                HttpRequestMessage request = new HttpRequestMessage();
                request.Method = HttpMethod.Post;

                var keysValues = new List<KeyValuePair<string, string>>();
                keysValues.Add(new KeyValuePair<string, string>("client_id", clientid));
                keysValues.Add(new KeyValuePair<string, string>("resource", url));
                keysValues.Add(new KeyValuePair<string, string>("username", username));
                keysValues.Add(new KeyValuePair<string, string>("password", password));
                keysValues.Add(new KeyValuePair<string, string>("grant_type", "password"));

                request.Content = new FormUrlEncodedContent(keysValues);

                HttpResponseMessage response = client.SendAsync(request).Result;

                return response.StatusCode == HttpStatusCode.OK;
            }
        }

Grant Type – Client Credentials

  public void OnGet()
        {
            var contacts = CrmRequest(
                HttpMethod.Get,
                "https://tessla010.api.crm11.dynamics.com/api/data/v9.1/contacts")
                .Result.Content.ReadAsStringAsync();
            // Similarly you can make POST, PATCH & DELETE requests
        }

        public static async Task<string> AccessTokenGenerator()
        {
            string clientId = ""; // Your Azure AD Application ID
            string clientSecret = ""; // Client secret generated in your App
            string authority = "https://login.microsoftonline.com/{tenantid}"; // Azure AD App Tenant ID
            string resourceUrl = "https://tessla010.crm11.dynamics.com/"; // Your Dynamics 365 Organization URL

            var credentials = new ClientCredential(clientId, clientSecret);
            var authContext = new Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext(authority);
            var result = await authContext.AcquireTokenAsync(resourceUrl, credentials);
            return result.AccessToken;
        }

        public static async Task<HttpResponseMessage> CrmRequest(HttpMethod httpMethod, string requestUri, string body = null)
        {
            // Acquiring Access Token
            var accessToken = await AccessTokenGenerator();

            var client = new HttpClient();
            var message = new HttpRequestMessage(httpMethod, requestUri);

            // OData related headers
            message.Headers.Add("OData-MaxVersion", "4.0");
            message.Headers.Add("OData-Version", "4.0");
            message.Headers.Add("Prefer", "odata.include-annotations=\"*\"");

            // Passing AccessToken in Authentication header
            message.Headers.Add("Authorization", $"Bearer {accessToken}");

            // Adding body content in HTTP request
            if (body != null)
                message.Content = new StringContent(body, UnicodeEncoding.UTF8, "application/json");

            return await client.SendAsync(message);
        }

Grant Type – Client Credentials using the ADAL v3

This method is not recommended but serves as demonstration

class AccessDynamics
{
    private static string serviceUrl = "https://yourorg.crm.dynamics.com"; 
    private static string clientId = "51f81489-12ee-4a9e-aaae-a2591f45987d"; 
    private static string userName = "you@yourorg.onmicrosoft.com";
    private static string password = "yourpassword";

    static void Main(string[] args)
    {

        AuthenticationContext authContext = 
        new AuthenticationContext("https://login.microsoftonline.com/common", false);  
        UserCredential credential = new UserCredential(userName, password);
        AuthenticationResult result = authContext.AcquireToken(serviceUrl, clientId, credential);
        //The access token
        string accessToken = result.AccessToken;

        using (HttpClient client = new HttpClient()) {
        client.BaseAddress = new Uri(serviceUrl);
        client.Timeout = new TimeSpan(0, 2, 0);  //2 minutes  
        client.DefaultRequestHeaders.Add("OData-MaxVersion", "4.0");
        client.DefaultRequestHeaders.Add("OData-Version", "4.0");
        client.DefaultRequestHeaders.Accept.Add(
            new MediaTypeWithQualityHeaderValue("application/json"));
        HttpRequestMessage request = 
            new HttpRequestMessage(HttpMethod.Get, "/api/data/v9.0/WhoAmI");
        //Set the access token
        request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
        HttpResponseMessage response = client.SendAsync(request).Result;
        if (response.IsSuccessStatusCode)
        {
            //Get the response content and parse it.  
            JObject body = JObject.Parse(response.Content.ReadAsStringAsync().Result);
            Guid userId = (Guid)body["UserId"];
            Console.WriteLine("Your system user ID is: {0}", userId);
        }

    }
}