Reputation: 358
I am trying to connect with Postman to Dynamics365 CRM REST API. Although I obtain a token successfully without login using Grant Type client credentials I then get a 401 error when doing a sample GET to the API. My console application is working successfully however and is not prompting the user for login (I don't want a login prompt to appear).
I have: 1. Registered the app in Azure AD, 2. Created the client secret 3. Created the application user in Dynamics and linked via the Application ID to App from step 1
I've done this with two different apps and two different application users and get the same result in Postman i.e. Token retrieved but 401 error on GET.
The console app below is working with the same credentials, would appreciate any input on what is missing in the Postman config
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System.Net.Http.Headers;
using System.Net.Http;
using Newtonsoft.Json.Linq;
namespace ConsoleApp8
{
class Program
{
static void Main(string[] args)
{
const string ResourceId = "https://myurldev.crm4.dynamics.com/api/data/v9.1";
Task<AuthenticationResult> t = GetUserOAuthToken();
t.Wait();
string accessToken = t.Result.AccessToken;
Console.WriteLine("ACCESS TOKEN \n\n" + accessToken);
Console.WriteLine("\n\n Please any key to display content of the blob");
//Console.ReadKey();
using (HttpClient httpClient = new HttpClient())
{
httpClient.BaseAddress = new Uri(ResourceId);
httpClient.Timeout = new TimeSpan(0, 2, 0); // 2 minutes
httpClient.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", accessToken);
//Send the Get Incident request to the Web API using a GET request.
var response = httpClient.GetAsync("/incidents",
HttpCompletionOption.ResponseHeadersRead).Result;
if (response.IsSuccessStatusCode)
{
//Get the response content and parse it.
JObject body = JObject.Parse(response.Content.ReadAsStringAsync().Result);
string title = (string)body["title"];
Console.WriteLine("Incident title is : {0}", title);
}
else
{
Console.WriteLine("The request failed with a status of '{0}'",
response.ReasonPhrase);
}
}
/*
// Use the access token to create the storage credentials.
TokenCredential tokenCredential = new TokenCredential(accessToken);
StorageCredentials storageCredentials = new StorageCredentials(tokenCredential);
// Create a block blob using those credentials
CloudBlockBlob blob = new CloudBlockBlob(new Uri("https://placeholderURL/SalesOrder.json"), storageCredentials);
using (var stream = blob.OpenRead())
{
using (StreamReader reader = new StreamReader(stream))
{
while (!reader.EndOfStream)
{
Console.WriteLine(reader.ReadLine());
}
}
}
Console.WriteLine("\n\n Please any key to terminate the program");
Console.ReadKey();*/
}
static async Task<AuthenticationResult> GetUserOAuthToken()
{
const string ResourceId = "https://myurldev.crm4.dynamics.com/";
const string AuthInstance = "https://login.microsoftonline.com/{0}/";
const string TenantId = "XXXX-DYNAMICS_TENANT_ID-XXXXX"; // Tenant or directory ID
// Construct the authority string from the Azure AD OAuth endpoint and the tenant ID.
string authority = string.Format(System.Globalization.CultureInfo.InvariantCulture, AuthInstance, TenantId);
AuthenticationContext authContext = new AuthenticationContext(authority);
ClientCredential cc = new ClientCredential("XXXX_APPLICATION_ID_XXXX", "XXXXX_CLIENT_SECRET_XXXX");
// Acquire an access token from Azure AD.
AuthenticationResult result = await authContext.AcquireTokenAsync(ResourceId, cc);
return result;
}
}
}
I had already added the following permissions to my APP
This is the response when I analyse the token in JWT.io
Upvotes: 0
Views: 1462
Reputation: 15609
It seems that Dynamics CRM only support delegated permission which allow the application to access Common Data Service acting as users in the organization. This means client credentials is not appropriate here.
However, you said that you can use client credentials in console app. You can try with below request to get the access token.
Upvotes: 1