これを正常に行うには、次のすべてをセットアップする必要があることがわかりました。
- Azure AD でアプリケーション登録を作成します。
- Dynamics の API アクセス許可、具体的には「組織ユーザーとして Dynamics 365 にアクセスする」を付与します。
- 次のようなダミーの Web リダイレクト URI を指定します。
http://localhost/auth
- クライアント シークレットを生成し、後で使用するために保存する
- Azure AD でユーザー アカウントを作成し、Dynamics へのアクセス許可を付与します。
- 上記の非対話型ユーザー アカウントと同じ電子メールを使用して、Dynamics でアプリケーション ユーザー レコードを作成します。
- 作成したユーザー アカウントを使用してアプリケーションを認証します。
ステップ 4 では、新しいシークレット ウィンドウを開き、次のパターンを使用して URL を作成し、ステップ 2 でユーザー アカウントの資格情報を使用してログインします。
https://login.microsoftonline.com/<your aad tenant id>/oauth2/authorize?client_id=<client id>&response_type=code&redirect_uri=<redirect uri from step 1>&response_mode=query&resource=https://<organization name>.<region>.dynamics.com&state=<random value>
これが完了すると、Dynamics アプリケーション ユーザーにアプリケーション ID とアプリケーション ID URI があることがわかります。
これで、ClientId と ClientSecret、および他のいくつかの組織固有の変数を使用して、Azure Active Directory (AAD) で認証し、oauth トークンを取得してOrganizationWebProxyClient
. これを行う完全なコード例を見つけたことはありませんが、独自の目的で次のコードを開発しました。取得したトークンの有効期限は 1 時間です。
internal class ExampleClientProvider
{
// Relevant nuget packages:
// <package id="Microsoft.CrmSdk.CoreAssemblies" version="9.0.2.9" targetFramework="net472" />
// <package id="Microsoft.IdentityModel.Clients.ActiveDirectory" version="4.5.1" targetFramework="net461" />
// Relevant imports:
// using Microsoft.IdentityModel.Clients.ActiveDirectory;
// using Microsoft.Crm.Sdk.Messages;
// using Microsoft.Xrm.Sdk;
// using Microsoft.Xrm.Sdk.Client;
// using Microsoft.Xrm.Sdk.WebServiceClient;
private const string TenantId = "<your aad tenant id>"; // from your app registration overview "Directory (tenant) ID"
private const string ClientId = "<your client id>"; // from your app registration overview "Application (client) ID"
private const string ClientSecret = "<your client secret>"; // secret generated in step 1
private const string LoginUrl = "https://login.microsoftonline.com"; // aad login url
private const string OrganizationName = "<your organization name>"; // check your dynamics login url, e.g. https://<organization>.<region>.dynamics.com
private const string OrganizationRegion = "<your organization region>"; // might be crm for north america, check your dynamics login url
private string GetServiceUrl()
{
return $"{GetResourceUrl()}/XRMServices/2011/Organization.svc/web";
}
private string GetResourceUrl()
{
return $"https://{OrganizationName}.api.{OrganizationRegion}.dynamics.com";
}
private string GetAuthorityUrl()
{
return $"{LoginUrl}/{TenantId}";
}
public async Task<OrganizationWebProxyClient> CreateClient()
{
var context = new AuthenticationContext(GetAuthorityUrl(), false);
var token = await context.AcquireTokenAsync(GetResourceUrl(), new ClientCredential(ClientId, ClientSecret));
return new OrganizationWebProxyClient(new Uri(GetServiceUrl()), true)
{
HeaderToken = token.AccessToken,
SdkClientVersion = "9.1"
};
}
public async Task<OrganizationServiceContext> CreateContext()
{
var client = await CreateClient();
return new OrganizationServiceContext(client);
}
public async Task TestApiCall()
{
var context = await CreateContext();
// send a test request to verify authentication is working
var response = (WhoAmIResponse) context.Execute(new WhoAmIRequest());
}
}