- 記事一覧 >
- ブログ記事
Dataverse APIでsystemuserテーブルにAzure ADユーザーを同期
はじめに
Microsoft Dataverse の systemuser
テーブル に Azure AD ユーザーを同期しました。ユーザーが Dataverse(Power Apps)を使い始めたりすると、自動で同期するようですが、API でなんとかならないか、Postman を使って探ってみましたところ、なんとかなりましたので、紹介していきたいと思います。
systemuser
テーブル に Azure AD ユーザーを同期するだけの場合、Power Platform 管理センターから手動、Power Automate、Power Apps、Power Shell といろいろやり方が有るようでしたが、今回は、Microsoft Dataverse Web API で同期の方法 の話です。
Postman や Azure 準備手順については、前回記事、「Postmanを使ってMicrosoft Dataverse Web APIで部署を追加」にありますので、省略します。Postman インストール、アクセストークン準備済みとします。Azure Active Directory へのアプリ登録済みとします。
Dataverse 等の状況は、2022年10月現在の状況を元にしています。
やり方
なんと!
一行で終了します!
GET [Organization URI]/api/data/v9.2/systemusers(azureactivedirectoryobjectid=<user object ID>)
例:GET https://***********.api.crm*.dynamics.com/api/data/v9.2/systemusers(azureactivedirectoryobjectid=c74a8***-****-****-****-*******abb78)
だけです。POST ではなく、GET です。
<user object ID>
は、Azure Active Directory の ユーザーのオブジェクト ID です。これに当たる人が Dataverse の ユーザー
テーブル( systemuser
テーブル)にまだ登録されていない場合、登録されます。
既に登録されている場合、その人の systemuser
テーブルのレコード情報を返します。
ググりまくっても、なかなか分からず、API では、できないかと思いましたが、learn.microsoft.com
にサラっと書いてありました。
「Azure Active Directory グループのチームとの連携」(https://learn.microsoft.com/ja-jp/power-apps/developer/data-platform/aad-group-team
)
「Azure ユーザー オブジェクト識別子 (ID) を使用してユーザー行を取得できます。 ユーザーが Dataverse に存在しない場合、ユーザーが Dataverse に自動的に追加されます。」
↑
全く間違ったことを言っていないですが、あまりにもサラっと書いてあるので、別の話と思い、スルーしていました。
GET [Organization URI]/api/data/v9.0/SystemUser(azureactivedirectoryobjectid=<user object ID>)
は、2022年10月 時点では、誤植のようです。
GET [Organization URI]/api/data/v9.2/systemusers(azureactivedirectoryobjectid=<user object ID>)
でうまくいきました。
英語版も同じでした。(
https://learn.microsoft.com/en-us/power-apps/developer/data-platform/aad-group-team
)
結果
PowerApps - Dataverse ユーザー
テーブル( systemuser
テーブル)に以下のように登録されます。
GET https://***********.api.crm*.dynamics.com/api/data/v9.2/systemusers(azureactivedirectoryobjectid=c74a8***-****-****-****-*******abb78)
↓
↓
↓
PowerApps - Dataverse ユーザー
テーブル( systemuser
テーブル)に挿入されていることを確認できました。
表示列は適当に選別しました。
PATCH
登録したら、所属部署等は、PATCH リクエストで適宜登録情報を変更できます。
PATCH https://***********.api.crm*.dynamics.com/api/data/v9.2/systemusers(azureactivedirectoryobjectid=c74a8***-****-****-****-*******abb78)
{
"lastname": "テスト",
"firstname": "太郎",
"address1_telephone1": "090-0000-0000",
"businessunitid@odata.bind": "/businessunits(c74a8***-****-****-****-*******abb78)"
}
Dataverse ユーザー
テーブル( systemuser
テーブル)は、以下のようになります。
Azure Active Directory - <テナント> - ユーザー には反映されません。
DELETE
削除することもできました。
いきなり削除しようとすると、以下のエラーになりますので、いったん、状態
列( isdisabled
列)を true
にする必要があります。
{
"error": {
"code": "0x80048356",
"message": "User with SystemUserId=020fc***-****-****-****-*******279c8 is not disabled. Disable user before deletion.\""
}
}
PATCH https://***********.api.crm*.dynamics.com/api/data/v9.2/systemusers(azureactivedirectoryobjectid=c74a8***-****-****-****-*******abb78)
{
"isdisabled": true
}
これで、削除できると思いましたが、まだ問題ありです。Azure Active Directory - <テナント> - ユーザー の方を先に削除してくださいと言ってきます。
{
"error": {
"code": "0x80048359",
"message": "User with SystemUserId=020fc***-****-****-****-*******279c8 and AzureActiveDirectoryObjectId=c74a8***-****-****-****-*******abb78 is present in Azure Active Directory with state Exists. Please permanently delete user in Azure first."
}
}
無効にしたのだから、実質消えたようなものですが、なにがなんでも削除したい場合、Azure Active Directory - <テナント> - ユーザー の方を先に削除すると、Dataverse ユーザー
テーブル( systemuser
テーブル)から削除できました。
指示通り、Azure Active Directory - <テナント> - ユーザー の方を先に削除してもまだダメでした。
{
"error": {
"code": "0x80048359",
"message": "User with SystemUserId=020fc***-****-****-****-*******279c8 and AzureActiveDirectoryObjectId=c74a8***-****-****-****-*******abb78 is present in Azure Active Directory with state SoftDeleted. Please permanently delete user in Azure first."
}
}
完全に削除が必要でした。
DELETE https://***********.api.crm*.dynamics.com/api/data/v9.2/systemusers(azureactivedirectoryobjectid=c74a8***-****-****-****-*******abb78)
Dataverse ユーザー
テーブル( systemuser
テーブル)から消えます。
<user object ID> 確認方法
方法その1
PowerApps - Dataverse AAD User
テーブル( aaduser
テーブル)で確認できます。
A unique identifer for AAD User
列( id
列)
AAD user id
列( aaduserid
列)
が <user object ID>
に該当します。
方法その2
API で Get して確認できます。
GET https://***********.api.crm*.dynamics.com/api/data/v9.2/aadusers?$select=displayname
{
"@odata.context": "https://***********.api.crm*.dynamics.com/api/data/v9.2/$metadata#aadusers(displayname)",
"value": [
{
"displayname": "te st2",
"aaduserid": "********-****-****-****-************"
},
{
"displayname": "Test User1",
"aaduserid": "c74a8***-****-****-****-*******abb78"
},
{
"displayname": "test1",
"aaduserid": "********-****-****-****-************"
}
]
}
あるいは、ユーザー プリンシパル ID(サインイン ID)が分かっている場合、以下のようにもできます。
GET https://***********.api.crm*.dynamics.com/api/data/v9.2/aadusers?$select=aaduserid&$filter=userprincipalname eq 'testuser1@example.onmicrosoft.com'
{
"@odata.context": "https://***********.api.crm*.dynamics.com/api/data/v9.2/$metadata#aadusers(aaduserid)",
"value": [
{
"aaduserid": "c74a8***-****-****-****-*******abb78"
}
]
}
方法その3
Azure ポータル → Azure Active Directory → ユーザー → <該当ユーザー>
の オブジェクト ID で確認できます。
[Organization URI] 確認方法
Power Apps 右上の歯車 → 開発者リソース → Web API エンドポイント に表示される URL です。
試したこと(同期NGケース)
POST https://***********.api.crm*.dynamics.com/api/data/v9.2/systemusers
{
"fullname": "TESTUSER1",
"businessunitid@odata.bind": "/businessunits(********-****-****-****-************)",
"internalemailaddress": "testuser1@example.onmicrosoft.com"
}
↓
{
"error": {
"code": "0x80040217",
"message": "usersettings With Id = ********-****-****-****-************ Does Not Exist"
}
}
POST https://***********.api.crm*.dynamics.com/api/data/v9.2/systemusers
{
"azureactivedirectoryobjectid": "c74a8***-****-****-****-*******abb78"
}
↓
{
"error": {
"code": "0x80040530",
"message": "Unable to retrieve attribute=businessunitid for entityLogicalName=systemuser. Entity has Attribute Count=25. AttributeNames= preferredaddresscode, outgoingemaildeliverymethod, caltype, address1_addresstypecode, address1_shippingmethodcode, preferredphonecode, displayinserviceviews, incomingemaildeliverymethod, isdisabled, issyncwithdirectory, setupuser, accessmode, address2_addresstypecode, deletedstate, azurestate, defaultfilterspopulated, address2_shippingmethodcode, emailrouteraccessapproval, isintegrationuser, preferredemailcode, invitestatuscode, islicensed, systemuserid, isemailaddressapprovedbyo365admin, isactivedirectoryuser"
}
}
POST https://***********.api.crm*.dynamics.com/api/data/v9.2/systemusers
{
"azureactivedirectoryobjectid": "c74a8***-****-****-****-*******abb78",
"businessunitid@odata.bind": "/businessunits(********-****-****-****-************)"
}
↓
{
"error": {
"code": "0x80040200",
"message": "Attribute 'internalemailaddress' cannot be NULL"
}
}
POST https://***********.api.crm*.dynamics.com/api/data/v9.2/systemusers
{
"azureactivedirectoryobjectid": "c74a8***-****-****-****-*******abb78",
"businessunitid@odata.bind": "/businessunits(********-****-****-****-************)",
"internalemailaddress": "testuser1@example.onmicrosoft.com"
}
↓
{
"error": {
"code": "0x80040217",
"message": "usersettings With Id = ********-****-****-****-************ Does Not Exist"
}
}
POST https://***********.api.crm*.dynamics.com/api/data/v9.2/systemusers
{
"userid": "11111***-****-****-****-*******11111",
"azureactivedirectoryobjectid": "c74a8***-****-****-****-*******abb78",
"businessunitid@odata.bind": "/businessunits(********-****-****-****-************)",
"internalemailaddress": "testuser1@example.onmicrosoft.com"
}
↓
{
"error": {
"code": "0x0",
"message": "Error identified in Payload provided by the user for Entity :'systemusers', For more information on this error please follow this help link https://go.microsoft.com/fwlink/?linkid=2195293 ----> InnerException : Microsoft.Crm.CrmException: Invalid property 'userid' was found in entity 'Microsoft.Dynamics.CRM.systemuser'. ---> Microsoft.OData.ODataException: Does not support untyped value in non-open type.\r\n at System.Web.OData.Formatter.Deserialization.DeserializationHelpers.ApplyProperty(ODataProperty property, IEdmStructuredTypeReference resourceType, Object resource, ODataDeserializerProvider deserializerProvider, ODataDeserializerContext readContext)\r\n at Microsoft.Crm.Extensibility.CrmODataEntityDeserializer.ApplyStructuralProperty(Object resource, ODataProperty structuralProperty, IEdmStructuredTypeReference structuredType, ODataDeserializerContext readContext)\r\n --- End of inner exception stack trace ---\r\n at Microsoft.Crm.Extensibility.CrmODataEntityDeserializer.ApplyStructuralProperty(Object resource, ODataProperty structuralProperty, IEdmStructuredTypeReference structuredType, ODataDeserializerContext readContext)\r\n at System.Web.OData.Formatter.Deserialization.ODataResourceDeserializer.ApplyStructuralProperties(Object resource, ODataResourceWrapper resourceWrapper, IEdmStructuredTypeReference structuredType, ODataDeserializerContext readContext)\r\n at Microsoft.Crm.Extensibility.CrmODataEntityDeserializer.ApplyStructuralProperties(Object resource, ODataResourceWrapper resourceWrapper, IEdmStructuredTypeReference structuredType, ODataDeserializerContext readContext)\r\n at System.Web.OData.Formatter.Deserialization.ODataResourceDeserializer.ReadResource(ODataResourceWrapper resourceWrapper, IEdmStructuredTypeReference structuredType, ODataDeserializerContext readContext)\r\n at System.Web.OData.Formatter.ODataMediaTypeFormatter.ReadFromStream(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)."
}
}
POST https://***********.api.crm*.dynamics.com/api/data/v9.2/systemusers
{
"applicationid": "22222***-****-****-****-*******22222",
"azureactivedirectoryobjectid": "c74a8***-****-****-****-*******abb78",
"businessunitid@odata.bind": "/businessunits(********-****-****-****-************)",
"internalemailaddress": "testuser1@example.onmicrosoft.com"
}
↓
{
"error": {
"code": "0x8004f510",
"message": "We didn’t find that application ID c74a8***-****-****-****-*******abb78 in your Azure Active Directory (Azure AD) with CorrelationID c86*****-****-****-****-*********52d. Make sure your application is registered in Azure AD."
}
}
POST https://***********.api.crm*.dynamics.com/api/data/v9.2/systemusers
{
"applicationid": "<Azure Active Directory - アプリの登録で登録したアプリのアプリケーションID>",
"azureactivedirectoryobjectid": "c74a8***-****-****-****-*******abb78",
"businessunitid@odata.bind": "/businessunits(********-****-****-****-************)",
"internalemailaddress": "testuser1@example.onmicrosoft.com"
}
↓
エラーにならず、アプリケーションユーザーが登録されました。
が、削除すると、エラーになって、削除できなくなりました。真似して登録しないようにしてください。
消せない理由、消し方は、分かりませんでした。
DELETE https://***********.api.crm*.dynamics.com/api/data/v9.2/systemusers(********-****-****-****-************)
↓
{
"error": {
"code": "0x80040203",
"message": "MicrosoftGraphClient: Directory object Microsoft.Graph.ServicePrincipal with objectId ********-****-****-****-************ is NOT of User type."
}
}
GET https://***********.api.crm*.dynamics.com/api/data/v9.2/SystemUser(azureactivedirectoryobjectid=c74a8***-****-****-****-*******abb78)
↓
{
"error": {
"code": "0x8006088a",
"message": "Resource not found for the segment 'SystemUser'."
}
}
GET https://***********.api.crm*.dynamics.com/api/data/v9.2/systemusers(azureactivedirectoryobjectid=デタラメのID)
↓
{
"error": {
"code": "0x80060891",
"message": "A record with the specified key values does not exist in systemuser entity"
}
}
その他、宣伝、誹謗中傷等、当方が不適切と判断した書き込みは、理由の如何を問わず、投稿者に断りなく削除します。
書き込み内容について、一切の責任を負いません。
このコメント機能は、予告無く廃止する可能性があります。ご了承ください。
コメントの削除をご依頼の場合はTwitterのDM等でご連絡ください。