Dynamics CRM api HttpClient 请求使用 ADFS 3.0 进行身份验证
Dynamics CRM api HttpClient Request Authentication with ADFS 3.0
我有一个配置了 ADFS (3.0) 的本地 Dynamics 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 进行经过身份验证的调用(不提示登录 window,因为此应用程序是一项服务) .
我可以在 ADFS 上进行任何配置以便我的第一个示例工作吗?或者即使它是 ADFS 3.0 也可以用 Adal 来做吗?或任何其他解决方案...
我找到了问题的答案。这有点骇人听闻,但我自己测试过它并且有效。作为临时解决方案,这可以解决问题。
详情请见此处:https://community.dynamics.com/crm/f/117/t/255985
ADFS 3.0 支持授权代码流程,这就是我们将在这种情况下使用的内容。
我们需要检索授权码。通常在此步骤中,系统会提示 windows 用户输入其凭据。通过执行 POST 并发送 user/password 可以检索授权码。
- {authProvider} - ADFS Uri - 类似于
https://adfs.mycompany.com/adfs/oauth2/
- {ClientId} - Guid 用于
由您的基础架构团队将您的应用程序添加到 ADFS
- {RedirectUri} - 动态的 IFD Uri - 应该匹配重定向
Url 您的基础架构团队过去常常将您的应用程序添加到
ADFS
- 用户名 - 在 ADFS 和 Dynamics 中设置的用户
- password - 上述用户的密码
然后我们使用 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 之类的库检索令牌。这是解决方案的 hackish 部分。
- 现在我们有了授权码,我们需要检索访问令牌。
为此,我们需要进行以下调用
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 字符串,其中包含访问令牌。
- 使用访问令牌,调用 CRM rest API。
您需要将令牌附加到 header 中的 HttpClient 作为不记名令牌。
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer",token);
httpClient.DefaultRequestHeaders.Add("OData-MaxVersion", "4.0");
httpClient.DefaultRequestHeaders.Add("OData-Version", "4.0");
从现在开始,您可以调用 CRM api,您将获得授权。但是要小心,通常访问令牌是短暂的。您要么需要延长其生命周期,要么在每次过期时请求一个新令牌。
我有一个配置了 ADFS (3.0) 的本地 Dynamics 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 进行经过身份验证的调用(不提示登录 window,因为此应用程序是一项服务) .
我可以在 ADFS 上进行任何配置以便我的第一个示例工作吗?或者即使它是 ADFS 3.0 也可以用 Adal 来做吗?或任何其他解决方案...
我找到了问题的答案。这有点骇人听闻,但我自己测试过它并且有效。作为临时解决方案,这可以解决问题。
详情请见此处:https://community.dynamics.com/crm/f/117/t/255985
ADFS 3.0 支持授权代码流程,这就是我们将在这种情况下使用的内容。
我们需要检索授权码。通常在此步骤中,系统会提示 windows 用户输入其凭据。通过执行 POST 并发送 user/password 可以检索授权码。
- {authProvider} - ADFS Uri - 类似于 https://adfs.mycompany.com/adfs/oauth2/
- {ClientId} - Guid 用于 由您的基础架构团队将您的应用程序添加到 ADFS
- {RedirectUri} - 动态的 IFD Uri - 应该匹配重定向 Url 您的基础架构团队过去常常将您的应用程序添加到 ADFS
- 用户名 - 在 ADFS 和 Dynamics 中设置的用户
- password - 上述用户的密码
然后我们使用 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 之类的库检索令牌。这是解决方案的 hackish 部分。
- 现在我们有了授权码,我们需要检索访问令牌。
为此,我们需要进行以下调用
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 字符串,其中包含访问令牌。
- 使用访问令牌,调用 CRM rest API。
您需要将令牌附加到 header 中的 HttpClient 作为不记名令牌。
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer",token);
httpClient.DefaultRequestHeaders.Add("OData-MaxVersion", "4.0");
httpClient.DefaultRequestHeaders.Add("OData-Version", "4.0");
从现在开始,您可以调用 CRM api,您将获得授权。但是要小心,通常访问令牌是短暂的。您要么需要延长其生命周期,要么在每次过期时请求一个新令牌。