[英]Authorize WebApp to ADFS in order to access Dynamics CRM Web API
I have a web application that needs to speak with Dynamics CRM 365 Web API.我有一个需要与 Dynamics CRM 365 Web API 通信的 Web 应用程序。 The Dynamics CRM is configured as a Relying Party on ADFS.
Dynamics CRM 配置为 ADFS 上的依赖方。 The server is Windows Server 2016 and everything is on premise and not on Azure.
服务器是 Windows Server 2016,一切都在本地而不是 Azure 上。
What I did to acquire a valid token are the following:我为获得有效令牌所做的工作如下:
1) In ADFS went to Application Groups and add an new Server Application, took the ClientID and also generate a Client Secret for my web application. 1) 在 ADFS 中转到应用程序组并添加一个新的服务器应用程序,获取 ClientID 并为我的 Web 应用程序生成一个客户端密钥。
2) Add new new user in Active Directory the webAppUser 2) 在 Active Directory 中添加新用户 webAppUser
3) Add this user as an Application User in CRM with Application ID the ClientID I got earlier when I registered my web app to ADFS. 3) 将此用户添加为CRM 中的应用程序用户,其应用程序 ID 是我之前将 Web 应用程序注册到 ADFS 时获得的 ClientID。 Also created a new Role with full permissions on Entity Account and assign this role to this Application User
还创建了一个对实体帐户具有完全权限的新角色,并将此角色分配给此应用程序用户
4) I'm using the below code to retrieve a bearer token and add it to my HttpClient Authorization header. 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) I manage to get a token but when I call the CRM's Web Api I still get 401 Unauthorized. 5) 我设法获得了一个令牌,但是当我调用 CRM 的 Web Api 时,我仍然得到 401 Unauthorized。
At the end i had to use a system user and send it's credentials in my oAUth request using the code below in order to acquire a valid token:最后,我必须使用系统用户并使用下面的代码在我的 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;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.