授权WebApp访问ADFS以便访问Dynamics CRM Web API

15

我有一个网络应用程序需要与Dynamics CRM 365 Web API通信。 Dynamics CRM已配置为ADFS上的Relying Party。

服务器是Windows Server 2016,一切都在本地运行,而不是在Azure上。

我采取的步骤获取有效令牌如下:

1)在ADFS中转到“应用程序组”,添加一个新的服务器应用程序,获取ClientID并为我的Web应用程序生成客户端密码。

enter image description here

2)在Active Directory中添加新用户webAppUser

3)将此用户作为CRM中的应用程序用户添加,使用先前在ADFS上注册我的Web应用程序时获得的ClientID作为应用程序ID。还创建了一个具有对实体帐户的完全权限的新角色,并将此角色分配给此应用程序用户

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未经授权的错误消息。

1个回答

4

最后,我不得不使用系统用户,并使用以下代码在我的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;

这是哪个版本的ADFS?支持密码授权吗?显然是支持的,但您能再明确一些吗? - davidcarr
1
@davidcarr 这是安装了最新 ADFS 的 Windows Server 2016。 - Ricky Stam
@RickyStam 我有类似的情况,你能否澄清一下你所说的系统用户是什么意思?难道不是所有的用户都是由用户创建的吗? - tracer tong
@tracertong 我的意思是在AD中创建了一个用户,该用户不属于任何真实用户,但只在我的应用程序中使用他的用户名和密码。这就是为什么我称之为系统用户的原因。 - Ricky Stam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接