Авторизовать WebApp для ADFS для доступа к API-интерфейсу Dynamics CRM

У меня есть веб-приложение, которому необходимо поговорить с API-интерфейсом Dynamic CRM 365. Динамический CRM настроен как вспомогательная сторона в ADFS. Сервер - это Windows Server 2016, и все находится в помещении, а не на Azure.

То, что я сделал для получения действительного токена, следующее:

1) В ADFS перешли в группы приложений и добавили новое серверное приложение, взяли ClientID и также создали клиентский секрет для моего веб-приложения.

введите описание изображения здесь

2) Добавить нового пользователя в Active Directory webAppUser

3) Добавьте этого пользователя как пользователя приложения в CRM с идентификатором приложения ClientID, который я получил ранее, когда зарегистрировал свое веб-приложение в ADFS. Также была создана новая роль с полными разрешениями для учетной записи Entity и назначить эту роль этому пользователю приложения

4) Я использую приведенный ниже код для получения токена-носителя и добавления его в заголовок авторизации HttpClient.

public class CrmWebApiClient
{
    private HttpClient _httpClient;

    public CrmWebApiClient()
    {
        _httpClient = new HttpClient();
        _httpClient.BaseAddress = new Uri("https://crmbaseaddress.com");            
    }

    internal async Task Initialize()
    {
        try
        {               
            var authority = "https://adfsServerUrl/adfs/";
            var authContext = new AuthenticationContext(authority,false);
            var credentials = new ClientCredential(clientID,clientSecret);

            var authResult = await authContext.AcquireTokenAsync("https://crmbaseaddress.com", credentials);

            _httpClient.DefaultRequestHeaders.Authorization =
                new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
        }
        catch (Exception ex)
        {
            var error = ex;
        }

    }

    internal async Task<string> GetValuesAsync()
    {
        var result = string.Empty;
        try
        {
            result = await _httpClient.GetStringAsync("api/data/v8.1/accounts");
        }
        catch (Exception ex)
        {
            var error = ex;
        }

        return result;
    }
}

5) Мне удается получить токен, но когда я вызываю CRM Web Api, я все равно получаю 401 Unauthorized.

Вы можете мне помочь? Я на правильном пути? Должен ли я сделать что-нибудь еще?

Ответ 1

В конце мне пришлось использовать системного пользователя и отправить его учетные данные в моем запросе oAUth, используя следующий код, чтобы получить действительный токен:

namespace TestApp.App_Start {
public class CrmWebApiClient
{
    private HttpClient _httpClient;

    public CrmWebApiClient()
    {       
        _httpClient = new HttpClient();
        _httpClient.BaseAddress = new Uri("https://crmUrl");
        _httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        _httpClient.DefaultRequestHeaders.Add("OData-MaxVersion","4.0");
        _httpClient.DefaultRequestHeaders.Add("OData-Version", "4.0");
    }

    internal async Task Initilize()
    {
        try
        {

            var tokenClient = new HttpClient();             
            var content = new FormUrlEncodedContent(new[] {
                new KeyValuePair<string,string>("client_id",_clientID),
                new KeyValuePair<string,string>("client_secret",_clientSecret),
                new KeyValuePair<string,string>("resource",_urlOfResource),
                new KeyValuePair<string,string>("username",_usernameOfSystemUser),
                new KeyValuePair<string,string>("password",_passwordOfSystemUser),
                new KeyValuePair<string,string>("grant_type","password"),
            });
            var res = tokenClient.PostAsync("https://adfsUrl/adfs/oauth2/token", content);
            var respo = res.Result.Content.ReadAsStringAsync().Result;
            var accesstoken = JObject.Parse(respo).GetValue("access_token").ToString();

            _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accesstoken);

        }
        catch (Exception ex)
        {
            Trace.WriteLine($"Exception when requesting the bearer token from ADFS: {ex.Message} - {ex.InnerException?.Message}");
        }

    }

    internal async Task<string> GetAccountsAsync()
    {
        var result = string.Empty;
        try
        {
            result = _httpClient.GetStringAsync("/api/data/v8.0/accounts").Result;

        }
        catch (Exception ex)
        {
            Trace.WriteLine($"Exception when calling the CRM api: {ex.Message} - {ex.InnerException?.Message}");
        }
        return result;
    }
}
}


// Use the above class like that
var httpClient = new CrmWebApiClient();
httpClient.Initilize().Wait();
var result = httpClient.GetAccountsAsync().Result;