使用ADFS 3.0的动态CRM API HttpClient请求身份验证

时间:2018-10-30 20:18:19

标签: c# dynamics-crm adfs

我有一个配置有ADFS(3.0)的本地Dynamic CRM(2016)。当用户想要登录时,他们将被重定向到ADFS登录页面,并且用户输入其Windows AD凭据。

在.net核心应用程序中,我需要使用HttpClient向CRM API发出请求。当我尝试像往常一样为Windows Auth CRM发送凭据时,它不起作用。我收到401未经授权。如下所示。

HttpClient client = new HttpClient(new HttpClientHandler() { Credentials = new NetworkCredential("myuser", "mypassword", "mydomain") });
var result = client.GetAsync("https://mycrmaddress/api/data/v8.0/accounts");

我还尝试使用Adal检索令牌并将其作为不记名令牌附加到请求中,但是我无法使用adal获得令牌。当我尝试时,会收到以下消息:

The authorization server does not support the requested 'grant_type'. The authorization server only supports 'authorization_code'

ADFS 3.0不支持此流程。

我无法升级到ADFS 4.0,所以我想知道对经过身份验证的CRM api调用有哪些选择(由于此应用程序是服务,因此不会提示登录窗口)。

我可以在ADFS上进行任何配置,以便第一个示例工作吗?还是即使ADFS 3.0也可以使用Adal?或任何其他解决方案...

1 个答案:

答案 0 :(得分:2)

我找到了问题的答案。这有点黑,但是我自己测试了一下,而且效果很好。作为临时解决方案,可以解决问题。

详细信息在这里:https://community.dynamics.com/crm/f/117/t/255985


ADFS 3.0支持授权码流程,在这种情况下,我们将使用此功能。

  • 我们需要检索授权码。通常,在此步骤中,系统会提示用户输入窗口以输入其凭据。通过执行POST并发送用户名/密码,可以检索授权码。

    • {authProvider}-ADFS Uri-类似 https://adfs.mycompany.com/adfs/oauth2/
    • {ClientId}-该Guid过去 由基础架构团队将您的应用程序添加到ADFS
    • {RedirectUri}-动态的IFD Uri-应与重定向匹配 基础架构团队惯用的网址,用于将您的应用程序添加到 ADFS
    • 用户名-在ADFS和Dynamics中设置的用户
    • 密码-上述用户的密码

然后,我们使用HttpClient对这些信息进行以下调用。

var uri = $"{authProvider}authorize?response_type=code&client_id={clientId}&resource={redirectUri}&redirect_uri={redirectUri}";

var content = new FormUrlEncodedContent(new[] {
    new KeyValuePair<string,string>("username",username),
    new KeyValuePair<string,string>("password",password),
});

var responseResult = _httpManager.PostAsync(uri, content).Result;

响应内容将是一个html页面(通常请记住,此流程会提示用户登录页面)。在此页面中,将有一个包含授权代码的表格。使用类似HtmlAgilityPack的库检索令牌。这是该解决方案的主要内容。

  1. 现在我们有了授权码,需要检索访问令牌。

为此,我们需要拨打以下电话

var uri = $"{authProvider}token";
            var content = new FormUrlEncodedContent(new[] {
                new KeyValuePair<string,string>("grant_type","authorization_code"),
                new KeyValuePair<string,string>("client_id",clientId),
                new KeyValuePair<string,string>("redirect_uri",redirectUri),
                new KeyValuePair<string,string>("code",code)
            });

var response = await _httpManager.PostAsync(uri, content);

响应内容将是一个包含访问令牌的json字符串。

  1. 使用访问令牌,调用CRM Rest API。

您需要将令牌作为承载令牌附加到标头中的HttpClient。

httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer",token);
httpClient.DefaultRequestHeaders.Add("OData-MaxVersion", "4.0");
httpClient.DefaultRequestHeaders.Add("OData-Version", "4.0");

从现在开始,您可以调用CRM api,您将被授权。但是请注意,正常情况下访问令牌是短暂的。您将需要延长它们的生命周期,或者在每次过期时请求一个新令牌。