教學課程:在 Azure Active Directory 中開發和規劃 SCIM 端點的佈建

身為應用程式開發人員,您可以使用跨網域身分識別管理系統 (SCIM) 使用者管理 API,在您的應用程式與 Azure Active Directory (Azure AD) 之間啟用使用者和群組的自動佈建。 本文說明如何建置 SCIM 端點,並與 Azure AD 佈建服務整合。 SCIM 規格提供一般的使用者佈建結構描述。 與 SAML 或 OpenID Connect 等同盟標準使用時,SCIM 可為管理員提供端對端、以標準為基礎的存取管理解決方案。

使用 SCIM 從 Azure AD 佈建至應用程式

SCIM 2.0 是兩個端點的標準化定義:/Users 端點和 /Groups 端點。 其會使用常見的 REST API 端點來建立、更新及刪除物件。 SCIM 包含針對常見屬性預先定義的結構描述,例如群組名稱、使用者名稱、名字、姓氏和電子郵件。

提供 SCIM 2.0 REST API 的應用程式,可減輕或消除使用專屬使用者管理 API 的麻煩。 例如,任何符合規範的 SCIM 用戶端都知道如何對 /Users 端點進行 JSON 物件的 HTTP POST,以建立新的使用者項目。 符合 SCIM 標準的應用程式可以立即運用既有的用戶端、工具和程式碼,而無須使用略為不同的 API 來執行相同的基本動作。

定義於 SCIM 2.0 中用於管理的標準使用者物件結構描述和 REST API (RFC 764276437644),可讓識別提供者和應用程式更容易互相整合。 建置 SCIM 端點的應用程式開發人員可與任何符合 SCIM 規範的用戶端整合,而無須執行自訂工作。

若要自動佈建至應用程式,它需要建立並整合 Azure AD 佈建服務存取的 SCIM 端點。 請使用下列步驟,開始將使用者和群組佈建至您的應用程式。

  1. 設計您的使用者和群組結構描述 - 識別應用程式的物件和屬性,以判定如何將其對應至 Azure AD SCIM 實作所支援的使用者和群組結構描述。

  2. 了解 Azure AD SCIM 實作 - 了解如何實作 Azure AD 佈建服務,藉以建立 SCIM 通訊協定要求處理和回應的模型。

  3. 建立 SCIM 端點 - 端點必須與 SCIM 2.0 相容,才能與 Azure AD 佈建服務整合。 您可以選擇使用 Microsoft 通用語言基礎結構 (CLI) 程式庫和程式碼範例來建置您的端點。 這些範例僅供參考和測試之用;建議您在生產應用程式中不要依賴它們。

  4. 整合 SCIM 端點與 Azure AD 佈建服務。 如果您的組織使用第三方應用程式來實作 Azure AD 所支援的 SCIM 2.0 設定檔,則您可以快速地自動佈建與取消佈建使用者和群組。

  5. [選擇性] 將應用程式發佈至 Azure AD 應用程式庫 - 讓客戶輕鬆探索您的應用程式,並輕鬆地設定佈建。

圖表:顯示整合 SCIM 端點與 Azure AD 的所需步驟。

設計您的使用者和群組結構描述

每個應用程式都需要不同的屬性來建立使用者或群組。 識別應用程式所需的必要物件 (使用者、群組) 和屬性 (名稱、管理員、職稱等),以開始整合。

SCIM 標準定義了用來管理使用者和群組的結構描述。

「核心」使用者結構描述只需要三個屬性 (其他所有屬性都是選用屬性):

  • id,服務提供者定義的識別碼
  • userName,使用者的唯一識別碼 (一般會對應至 Azure AD 使用者主體名稱)
  • meta,服務提供者所維護的「唯讀」中繼資料

除了「核心」使用者結構描述以外,SCIM 標準還會定義「企業」使用者延伸模組,而此延伸模組包含用於擴充使用者結構描述以符合應用程式需求的模型。

例如,如果您的應用程式需要使用者的電子郵件和使用者的管理員,則請使用「核心」結構描述來收集使用者的電子郵件,並使用「企業」使用者結構描述來收集使用者的管理員。

若要設計結構描述,請遵循下列步驟:

  1. 列出您的應用程式所需的屬性,然後分類為驗證所需的屬性 (例如 loginName 和 email)。 需要屬性來管理使用者生命週期 (例如狀態 / 使用中),以及應用程式 (運作所需的其他所有屬性,例如管理員、標記)。

  2. 檢查這些屬性已定義於「核心」使用者結構描述還是「企業」使用者結構描述中。 如果沒有,則您必須將延伸模組定義為涵蓋遺漏屬性的使用者結構描述。 請參閱下列範例,以取得允許佈建使用者 tag 的使用者延伸模組。

  3. 將 SCIM 屬性對應至 Azure AD 中的使用者屬性。 如果您在 SCIM 端點中定義的其中一個屬性在 Azure AD 使用者結構描述上沒有明確的對應項目,請引導租用戶管理員展開其結構描述,或使用延伸模組屬性,如以下所示的 tags 屬性。

下表列出必要屬性的範例:

必要的應用程式屬性 已對應的 SCIM 屬性 已對應的 Azure AD 屬性
loginName userName userPrincipalName
firstName name.givenName givenName
lastName name.familyName surName
workMail emails[type eq "work"].value Mail
manager manager manager
tag urn:ietf:params:scim:schemas:extension:CustomExtensionName:2.0:User:tag extensionAttribute1
status 作用中 isSoftDeleted (未儲存使用者的計算值)

下列 JSON 酬載顯示 SCIM 結構描述範例:

{
     "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User",
      "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User",
      "urn:ietf:params:scim:schemas:extension:CustomExtensionName:2.0:User"],
     "userName":"bjensen@testuser.com",
     "id": "48af03ac28ad4fb88478",
     "externalId":"bjensen",
     "name":{
       "familyName":"Jensen",
       "givenName":"Barbara"
     },
     "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User": {
     "Manager": "123456"
   },
     "urn:ietf:params:scim:schemas:extension:CustomExtensionName:2.0:User": {
     "tag": "701984",
   },
   "meta": {
     "resourceType": "User",
     "created": "2010-01-23T04:56:22Z",
     "lastModified": "2011-05-13T04:42:34Z",
     "version": "W\/\"3694e05e9dff591\"",
     "location":
 "https://example.com/v2/Users/2819c223-7f76-453a-919d-413861904646"
   }
}   

注意

除了應用程式所需的屬性以外,JSON 表示法還包括必要的 idexternalIdmeta 屬性。

它有助於在 /User/Group 之間分類,以將 Azure AD 中的任何預設使用者屬性對應至 SCIM RFC,請參閱自訂在 Azure AD 與 SCIM 端點之間對應屬性的方式

下表列出使用者屬性的範例:

Azure AD 使用者 urn:ietf:params:scim:schemas:extension:enterprise:2.0:User
IsSoftDeleted 作用中
department urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:department
displayName displayName
employeeId urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:employeeNumber
Facsimile-TelephoneNumber phoneNumbers[type eq "fax"].value
givenName name.givenName
jobTitle title
mail emails[type eq "work"].value
mailNickname externalId
manager urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:manager
mobile phoneNumbers[type eq "mobile"].value
postalCode addresses[type eq "work"].postalCode
proxy-Addresses emails[type eq "other"].Value
physical-Delivery-OfficeName addresses[type eq "other"].Formatted
streetAddress addresses[type eq "work"].streetAddress
surname name.familyName
telephone-Number phoneNumbers[type eq "work"].value
user-PrincipalName userName

下表列出群組屬性的範例:

Azure AD 群組 urn:ietf:params:scim:schemas:core:2.0:Group
displayName displayName
members members
objectId externalId

注意

您不需要同時支援使用者和群組,或此處顯示的所有屬性,這只是 Azure AD 中的屬性通常會如何對應至 SCIM 通訊協定中屬性的參考。

SCIM RFC 中定義了數個端點。 您可以從 /User 端點開始,然後再向外擴充。 下表列出一些 SCIM 端點:

端點 描述
/User 對使用者物件執行 CRUD 作業。
/Group 對群組物件執行 CRUD 作業。
/Schemas 每個用戶端和服務提供者所支援的屬性集可能有所不同。 一個服務提供者可能包括 nametitleemails,而另一個服務提供者則使用 nametitlephoneNumbers。 結構描述端點可讓您探索支援的屬性。
/Bulk 大量作業可讓您在單一作業中對大型資源物件集合執行作業 (例如,更新大型群組的成員資格)。
/ServiceProviderConfig 提供支援之 SCIM 標準功能的詳細資料,例如,支援的資源和驗證方法。
/ResourceTypes 指定每個資源的中繼資料。

注意

使用 /Schemas 端點可支援自訂屬性,或您的結構描述經常變更時,因為它可讓用戶端自動擷取最新的結構描述。 使用 /Bulk 端點來支援群組。

了解 Azure AD SCIM 實作

為了支援 SCIM 2.0 使用者管理 API,本節說明如何實作 Azure AD 佈建服務,並顯示如何建立 SCIM 通訊協定要求處理和回應的模型。

重要

Azure AD SCIM 實作行為的上次更新日期為 2018 年 12 月 18 日。 如需已變更內容的資訊,請參閱 Azure AD 使用者佈建服務的 SCIM 2.0 通訊協定合規性

SCIM 2.0 通訊協定規格內,您的應用程式必須支援下列需求:

需求 參考注意事項 (SCIM 通訊協定)
建立使用者,也可選擇性地建立群組 第 3.3 節
使用 PATCH 要求來修改使用者或群組 第 3.5.2 節。 支援可確保以高效能的方式佈建群組和使用者。
為稍早建立的使用者或群組擷取已知的資源 第 3.4.1 節
查詢使用者或群組 第 3.4.2 節。 依預設會按 id 擷取使用者,並按 usernameexternalId 加以查詢,以及按 displayName 查詢群組。
查詢群組資源時的篩選 excludedAttributes=members 3.4.2.2
支援列出使用者和分頁 第 3.4.2.4 節
虛刪除使用者 active=false 以及還原使用者 active=true 不論使用者是否為作用中,都應該在要求中傳回使用者物件。 只在從應用程式中將使用者實刪除時,才不應傳回該使用者。
支援 /Schemas 端點 第 7 節:將使用結構描述探索端點來探索其他屬性。
接受以單一持有人權杖對應用程式進行 Azure AD 的驗證和授權。

實作 SCIM 端點時,請使用一般指導方針,以確保與 Azure AD 的相容性:

一般:

  • id 是所有資源的必要屬性。 傳回資源的每個回應均應確保每個資源都具有此屬性,但不含元素的 ListResponse 除外。
  • 傳送的值應該使用與傳入的值相同的格式來儲存。 應該使用描述性、可採取動作的錯誤訊息來拒絕不正確值。 Azure AD 所傳送的資料與 SCIM 應用程式中儲存的資料之間不應該進行資料轉換。 (例如。 傳送為 55555555555 的電話號碼不應該儲存/傳回為 +5 (555) 555-5555)
  • 您不需要在 PATCH 回應中包含整個資源。
  • 對於 SCIM 中的結構元素,不需要大小寫相符項目,特別是 PATCHop 作業值,如第 3.5.2 節中所定義。 Azure AD 會將 op 的值發出為 [新增]、[取代] 和 [移除]。
  • Microsoft Azure AD 會要求提取隨機的使用者和群組,以確保端點和認證都是有效的。 此作業也可在 Azure 入口網站的 [測試連線] 流程中完成。
  • 您的 SCIM 端點支援 HTTPS。
  • 支援自訂複雜和多重值屬性,但是 Azure AD 沒有許多複雜的資料結構,無法在這些情況下提取資料。 簡單成對名稱/值類型複雜屬性可以輕鬆地對應,但目前不支援將資料傳送至具有三個以上子屬性的複雜屬性。
  • 多重值複雜屬性的 "type" 子屬性值必須是唯一的。 例如,不能有兩個不同的電子郵件地址具有 "work" 子類型。
  • 所有回應的標頭都應為 content-Type: application/scim+json

擷取資源:

  • 查詢/篩選要求的回應應一律為 ListResponse
  • Microsoft Azure AD 只會使用下列運算子:eqand
  • 資源可供查詢的屬性應該在 Azure 入口網站中設定為應用程式的比對屬性,請參閱自訂使用者佈建屬性對應

/Users:

  • 不支援 entitlements 屬性。
  • 任何視為使用者唯一性的屬性都必須可作為已篩選查詢的一部分使用。 (例如,如果同時評估 userName 和 emails[type eq "work"] 的使用者唯一性,則使用篩選對 /Users 進行的 GET 作業必須允許 userName eq "user@contoso.com"emails[type eq "work"].value eq "user@contoso.com" 查詢。

/Groups:

  • 群組是選用項目,但只有在 SCIM 實作支援 PATCH 要求時,才受到支援。
  • 群組必須具有 'displayName' 值的唯一性,才能與 Azure AD 和 SCIM 應用程式相符。 這不是 SCIM 通訊協定的需求,而是將 SCIM 服務與 Azure Active Directory 整合的需求。

/Schemas (結構描述探索):

  • 範例要求/回應
  • 自訂非資源庫 SCIM 應用程式目前不支援結構描述探索,但它正用於特定資源庫應用程式。 接下來,將會使用結構描述探索作為下列作業的唯一方法:將其他屬性新增至現有資源庫 SCIM 應用程式的結構描述。
  • 如果值不存在,請勿傳送 Null 值。
  • 屬性值應該是駝峰式大小寫 (例如 readWrite)。
  • 必須傳回清單回應。
  • 每次有人將佈建設定儲存至 Azure 入口網站時,或每次使用者登入 Azure 入口網站的編輯佈建頁面時,Azure AD 佈建服務都會提出 /schemas 要求。 在目標屬性清單的屬性對應中,會向客戶顯示任何探索到的其他屬性。 結構描述探索只會導致新增其他目標屬性。 它不會導致移除屬性。

使用者佈建和取消佈建

下圖顯示 Azure AD 傳送至 SCIM 端點的訊息,藉以管理應用程式身分識別存放區中使用者的生命週期。

圖表:顯示使用者佈建和取消佈建順序。

群組佈建和取消佈建

群組佈建和取消佈建是選擇性的。 在實作並啟用時,下圖顯示 Azure AD 會傳送至 SCIM 端點的訊息,以管理您應用程式的身分識別存放區中的群組生命週期。 這些訊息與使用者的訊息有兩方面的不同:

  • 擷取群組的要求會指定將成員屬性從回應要求中提供的任何資源中排除。
  • 要求判斷參考屬性是否具有特定值,會是有關成員屬性的要求。

下圖顯示群組取消佈建順序:

圖表:顯示群組佈建和取消佈建順序。

SCIM 通訊協定要求和回應

本文提供 Azure Active Directory (Azure AD) 佈建服務和範例預期回應所發出的 SCIM 要求範例。 為了獲得最佳結果,您應撰寫應用程式程式碼,以按此格式處理這些要求,並發出預期的回應。

重要

若要了解 Azure AD 使用者佈建服務發出下列作業的方式和時間,請參閱佈建週期:初始和增量一節 (位於佈建運作方式中)。

使用者作業

群組作業

結構描述探索

使用者作業

  • 可依 userNameemails[type eq "work"] 屬性來查詢使用者。

建立使用者

要求

POST /Users

{
    "schemas": [
        "urn:ietf:params:scim:schemas:core:2.0:User",
        "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"],
    "externalId": "0a21f0f2-8d2a-4f8e-bf98-7363c4aed4ef",
    "userName": "Test_User_ab6490ee-1e48-479e-a20b-2d77186b5dd1",
    "active": true,
    "emails": [{
        "primary": true,
        "type": "work",
        "value": "Test_User_fd0ea19b-0777-472c-9f96-4f70d2226f2e@testuser.com"
    }],
    "meta": {
        "resourceType": "User"
    },
    "name": {
        "formatted": "givenName familyName",
        "familyName": "familyName",
        "givenName": "givenName"
    },
    "roles": []
}
回應

HTTP/1.1 201 已建立

{
    "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
    "id": "48af03ac28ad4fb88478",
    "externalId": "0a21f0f2-8d2a-4f8e-bf98-7363c4aed4ef",
    "meta": {
        "resourceType": "User",
        "created": "2018-03-27T19:59:26.000Z",
        "lastModified": "2018-03-27T19:59:26.000Z"
    },
    "userName": "Test_User_ab6490ee-1e48-479e-a20b-2d77186b5dd1",
    "name": {
        "formatted": "givenName familyName",
        "familyName": "familyName",
        "givenName": "givenName",
    },
    "active": true,
    "emails": [{
        "value": "Test_User_fd0ea19b-0777-472c-9f96-4f70d2226f2e@testuser.com",
        "type": "work",
        "primary": true
    }]
}

取得使用者

要求

GET /Users/5d48a0a8e9f04aa38008

回應 (找到使用者)

HTTP/1.1 200 OK

{
    "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
    "id": "5d48a0a8e9f04aa38008",
    "externalId": "58342554-38d6-4ec8-948c-50044d0a33fd",
    "meta": {
        "resourceType": "User",
        "created": "2018-03-27T19:59:26.000Z",
        "lastModified": "2018-03-27T19:59:26.000Z"
    },
    "userName": "Test_User_feed3ace-693c-4e5a-82e2-694be1b39934",
    "name": {
        "formatted": "givenName familyName",
        "familyName": "familyName",
        "givenName": "givenName",
    },
    "active": true,
    "emails": [{
        "value": "Test_User_22370c1a-9012-42b2-bf64-86099c2a1c22@testuser.com",
        "type": "work",
        "primary": true
    }]
}
要求

GET /Users/5171a35d82074e068ce2

回應 (找不到使用者。不需要詳細資料,只需要狀態。)
{
    "schemas": [
        "urn:ietf:params:scim:api:messages:2.0:Error"
    ],
    "status": "404",
    "detail": "Resource 23B51B0E5D7AE9110A49411D@7cca31655d49f3640a494224 not found"
}

依查詢取得使用者

要求

GET /Users?filter=userName eq "Test_User_dfeef4c5-5681-4387-b016-bdf221e82081"

回應

HTTP/1.1 200 OK

{
    "schemas": ["urn:ietf:params:scim:api:messages:2.0:ListResponse"],
    "totalResults": 1,
    "Resources": [{
        "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
        "id": "2441309d85324e7793ae",
        "externalId": "7fce0092-d52e-4f76-b727-3955bd72c939",
        "meta": {
            "resourceType": "User",
            "created": "2018-03-27T19:59:26.000Z",
            "lastModified": "2018-03-27T19:59:26.000Z"
            
        },
        "userName": "Test_User_dfeef4c5-5681-4387-b016-bdf221e82081",
        "name": {
            "familyName": "familyName",
            "givenName": "givenName"
        },
        "active": true,
        "emails": [{
            "value": "Test_User_91b67701-697b-46de-b864-bd0bbe4f99c1@testuser.com",
            "type": "work",
            "primary": true
        }]
    }],
    "startIndex": 1,
    "itemsPerPage": 20
}

依查詢取得使用者 - 零個結果

要求

GET /Users?filter=userName eq "non-existent user"

回應

HTTP/1.1 200 OK

{
    "schemas": ["urn:ietf:params:scim:api:messages:2.0:ListResponse"],
    "totalResults": 0,
    "Resources": [],
    "startIndex": 1,
    "itemsPerPage": 20
}

更新使用者 [多重值屬性]

要求

PATCH /Users/6764549bef60420686bc HTTP/1.1

{
    "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
    "Operations": [
            {
            "op": "Replace",
            "path": "emails[type eq \"work\"].value",
            "value": "updatedEmail@microsoft.com"
            },
            {
            "op": "Replace",
            "path": "name.familyName",
            "value": "updatedFamilyName"
            }
    ]
}
回應

HTTP/1.1 200 OK

{
    "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
    "id": "6764549bef60420686bc",
    "externalId": "6c75de36-30fa-4d2d-a196-6bdcdb6b6539",
    "meta": {
        "resourceType": "User",
        "created": "2018-03-27T19:59:26.000Z",
        "lastModified": "2018-03-27T19:59:26.000Z"
    },
    "userName": "Test_User_fbb9dda4-fcde-4f98-a68b-6c5599e17c27",
    "name": {
        "formatted": "givenName updatedFamilyName",
        "familyName": "updatedFamilyName",
        "givenName": "givenName"
    },
    "active": true,
    "emails": [{
        "value": "updatedEmail@microsoft.com",
        "type": "work",
        "primary": true
    }]
}

更新使用者 [單一值屬性]

要求

PATCH /Users/5171a35d82074e068ce2 HTTP/1.1

{
    "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
    "Operations": [{
        "op": "Replace",
        "path": "userName",
        "value": "5b50642d-79fc-4410-9e90-4c077cdd1a59@testuser.com"
    }]
}
回應

HTTP/1.1 200 OK

{
    "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
    "id": "5171a35d82074e068ce2",
    "externalId": "aa1eca08-7179-4eeb-a0be-a519f7e5cd1a",
    "meta": {
        "resourceType": "User",
        "created": "2018-03-27T19:59:26.000Z",
        "lastModified": "2018-03-27T19:59:26.000Z"
        
    },
    "userName": "5b50642d-79fc-4410-9e90-4c077cdd1a59@testuser.com",
    "name": {
        "formatted": "givenName familyName",
        "familyName": "familyName",
        "givenName": "givenName",
    },
    "active": true,
    "emails": [{
        "value": "Test_User_49dc1090-aada-4657-8434-4995c25a00f7@testuser.com",
        "type": "work",
        "primary": true
    }]
}

停用使用者

要求

PATCH /Users/5171a35d82074e068ce2 HTTP/1.1

{
    "Operations": [
        {
            "op": "Replace",
            "path": "active",
            "value": false
        }
    ],
    "schemas": [
        "urn:ietf:params:scim:api:messages:2.0:PatchOp"
    ]
}
回應
{
    "schemas": [
        "urn:ietf:params:scim:schemas:core:2.0:User"
    ],
    "id": "CEC50F275D83C4530A495FCF@834d0e1e5d8235f90a495fda",
    "userName": "deanruiz@testuser.com",
    "name": {
        "familyName": "Harris",
        "givenName": "Larry"
    },
    "active": false,
    "emails": [
        {
            "value": "gloversuzanne@testuser.com",
            "type": "work",
            "primary": true
        }
    ],
    "addresses": [
        {
            "country": "ML",
            "type": "work",
            "primary": true
        }
    ],
    "meta": {
        "resourceType": "Users",
        "location": "/scim/5171a35d82074e068ce2/Users/CEC50F265D83B4530B495FCF@5171a35d82074e068ce2"
    }
}

刪除使用者

要求

DELETE /Users/5171a35d82074e068ce2 HTTP/1.1

回應

HTTP/1.1 204 沒有內容

群組作業

  • 群組應一律以空的成員清單建立。
  • 可依 displayName 屬性來查詢群組。
  • 群組 PATCH 要求的更新應會在回應中產生 HTTP 204 沒有內容。 不建議傳回列出所有成員的本文。
  • 不需要支援傳回群組的所有成員。

建立群組

要求

POST /Groups HTTP/1.1

{
    "schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group", "http://schemas.microsoft.com/2006/11/ResourceManagement/ADSCIM/2.0/Group"],
    "externalId": "8aa1a0c0-c4c3-4bc0-b4a5-2ef676900159",
    "displayName": "displayName",
    "meta": {
        "resourceType": "Group"
    }
}
回應

HTTP/1.1 201 已建立

{
    "schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
    "id": "927fa2c08dcb4a7fae9e",
    "externalId": "8aa1a0c0-c4c3-4bc0-b4a5-2ef676900159",
    "meta": {
        "resourceType": "Group",
        "created": "2018-03-27T19:59:26.000Z",
        "lastModified": "2018-03-27T19:59:26.000Z"
        
    },
    "displayName": "displayName",
    "members": []
}

取得群組

要求

GET /Groups/40734ae655284ad3abcc?excludedAttributes=members HTTP/1.1

回應

HTTP/1.1 200 OK

{
    "schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
    "id": "40734ae655284ad3abcc",
    "externalId": "60f1bb27-2e1e-402d-bcc4-ec999564a194",
    "meta": {
        "resourceType": "Group",
        "created": "2018-03-27T19:59:26.000Z",
        "lastModified": "2018-03-27T19:59:26.000Z"
    },
    "displayName": "displayName",
}

依 displayName 取得群組

要求

GET /Groups?excludedAttributes=members&filter=displayName eq "displayName" HTTP/1.1

回應

HTTP/1.1 200 OK

{
    "schemas": ["urn:ietf:params:scim:api:messages:2.0:ListResponse"],
    "totalResults": 1,
    "Resources": [{
        "schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
        "id": "8c601452cc934a9ebef9",
        "externalId": "0db508eb-91e2-46e4-809c-30dcbda0c685",
        "meta": {
            "resourceType": "Group",
            "created": "2018-03-27T22:02:32.000Z",
            "lastModified": "2018-03-27T22:02:32.000Z",
            
        },
        "displayName": "displayName",
    }],
    "startIndex": 1,
    "itemsPerPage": 20
}

更新群組 [非成員屬性]

要求

PATCH /Groups/fa2ce26709934589afc5 HTTP/1.1

{
    "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
    "Operations": [{
        "op": "Replace",
        "path": "displayName",
        "value": "1879db59-3bdf-4490-ad68-ab880a269474updatedDisplayName"
    }]
}
回應

HTTP/1.1 204 沒有內容

更新群組 [新增成員]

要求

PATCH /Groups/a99962b9f99d4c4fac67 HTTP/1.1

{
    "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
    "Operations": [{
        "op": "Add",
        "path": "members",
        "value": [{
            "$ref": null,
            "value": "f648f8d5ea4e4cd38e9c"
        }]
    }]
}
回應

HTTP/1.1 204 沒有內容

更新群組 [移除成員]

要求

PATCH /Groups/a99962b9f99d4c4fac67 HTTP/1.1

{
    "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
    "Operations": [{
        "op": "Remove",
        "path": "members",
        "value": [{
            "$ref": null,
            "value": "f648f8d5ea4e4cd38e9c"
        }]
    }]
}
回應

HTTP/1.1 204 沒有內容

刪除群組

要求

DELETE /Groups/cdb1ce18f65944079d37 HTTP/1.1

回應

HTTP/1.1 204 沒有內容

結構描述探索

探索結構描述

要求

GET /Schemas

回應

HTTP/1.1 200 OK

{
    "schemas": [
        "urn:ietf:params:scim:api:messages:2.0:ListResponse"
    ],
    "itemsPerPage": 50,
    "startIndex": 1,
    "totalResults": 3,
    "Resources": [
  {
    "schemas": ["urn:ietf:params:scim:schemas:core:2.0:Schema"],
    "id" : "urn:ietf:params:scim:schemas:core:2.0:User",
    "name" : "User",
    "description" : "User Account",
    "attributes" : [
      {
        "name" : "userName",
        "type" : "string",
        "multiValued" : false,
        "description" : "Unique identifier for the User, typically
used by the user to directly authenticate to the service provider.
Each User MUST include a non-empty userName value.  This identifier
MUST be unique across the service provider's entire set of Users.
REQUIRED.",
        "required" : true,
        "caseExact" : false,
        "mutability" : "readWrite",
        "returned" : "default",
        "uniqueness" : "server"
      },                
    ],
    "meta" : {
      "resourceType" : "Schema",
      "location" :
        "/v2/Schemas/urn:ietf:params:scim:schemas:core:2.0:User"
    }
  },
  {
    "schemas": ["urn:ietf:params:scim:schemas:core:2.0:Schema"],
    "id" : "urn:ietf:params:scim:schemas:core:2.0:Group",
    "name" : "Group",
    "description" : "Group",
    "attributes" : [
      {
        "name" : "displayName",
        "type" : "string",
        "multiValued" : false,
        "description" : "A human-readable name for the Group.
REQUIRED.",
        "required" : false,
        "caseExact" : false,
        "mutability" : "readWrite",
        "returned" : "default",
        "uniqueness" : "none"
      },
    ],
    "meta" : {
      "resourceType" : "Schema",
      "location" :
        "/v2/Schemas/urn:ietf:params:scim:schemas:core:2.0:Group"
    }
  },
  {
    "schemas": ["urn:ietf:params:scim:schemas:core:2.0:Schema"],
    "id" : "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User",
    "name" : "EnterpriseUser",
    "description" : "Enterprise User",
    "attributes" : [
      {
        "name" : "employeeNumber",
        "type" : "string",
        "multiValued" : false,
        "description" : "Numeric or alphanumeric identifier assigned
to a person, typically based on order of hire or association with an
organization.",
        "required" : false,
        "caseExact" : false,
        "mutability" : "readWrite",
        "returned" : "default",
        "uniqueness" : "none"
      },
    ],
    "meta" : {
      "resourceType" : "Schema",
      "location" :
"/v2/Schemas/urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"
    }
  }
]
}

安全性需求

TLS 通訊協定版本

可接受的 TLS 通訊協定版本只有 TLS 1.2 和 TLS 1.3。 不允許其他 TLS 版本。 不允許任何版本的 SSL。

  • RSA 金鑰必須至少有 2,048 位元。
  • ECC 金鑰必須至少有 256 位元,並使用已核准的橢圓曲線產生

金鑰長度

所有服務都必須使用以長度足夠的密碼編譯金鑰產生的 X.509 憑證,亦即:

加密套件

所有服務都必須設定為使用下列加密套件,並且依循以下指定的確切順序。 如果您只有一個 RSA 憑證,則安裝的 ECDSA 加密套件不會有任何作用。

TLS 1.2 加密套件的最低標準:

  • TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
  • TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
  • TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
  • TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
  • TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
  • TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
  • TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
  • TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384

IP 範圍

Azure AD 佈建服務目前可在 AzureActiveDirectory 的 IP 範圍下運作,如這裡所列出的。 您可以新增 AzureActiveDirectory 標籤底下所列的 IP 範圍,以允許來自 Azure AD 佈建服務的流量進入您的應用程式。 您必須仔細檢閱計算位址的 IP 範圍清單。 '40.126.25.32' 這類位址可能會在 IP 範圍清單中表示為 '40.126.0.0/18'。 您也可以使用下列 API,以程式設計方式取出 IP 範圍清單。

Azure AD 也支援代理程式型解決方案,以在私人網路 (內部部署、裝載於 Azure、裝載於 AWS 等) 中提供應用程式的連線能力。 客戶可以部署輕量型代理程式,而此代理程式提供 Azure AD 在私人網路的伺服器上的連線能力,而不需要開啟任何輸入連接埠。 在此深入了解。

建置 SCIM 端點

現在,您已設計結構描述並了解 Azure AD SCIM 實作,接著即可開始開發您的 SCIM 端點。 您可以利用 SCIM 社群所發佈的一些開放原始碼 SCIM 程式庫,而不要從頭開始完全靠自己建立實作。

如需如何建置 SCIM 端點 (包括範例) 的指導,請參閱開發範例 SCIM 端點

開放原始碼 .NET Core 參考程式碼範例由 Azure AD 佈建小組所發佈,這項資源可讓您立即開始進行開發。 建立 SCIM 端點後,您會想要加以測試。您可以使用在參考程式碼中提供的 postman 測試集合,或透過上方提供的範例要求/回應來執行。

注意

參考程式碼以「原狀」提供,目的是要協助您開始建置 SCIM 端點。歡迎社群供稿,以協助建置和維護程式碼。

解決方案是由兩個專案所組成:Microsoft.SCIMMicrosoft.SCIM.WebHostSample

Microsoft.SCIM 專案是一個程式庫,會定義符合 SCIM 規格的 Web 服務元件。 此專案會宣告 Microsoft.SCIM.IProvider 介面,要求會轉譯為對提供者方法的呼叫,而這些方法會設計為程式在身分識別存放區上運作。

明細:要求轉譯為對提供者方法的呼叫

Microsoft.SCIM.WebHostSample 專案是 ASP.NET Core Web 應用程式,藉以空白範本為基礎。 此專案可讓範例程式碼獨立部署,裝載於容器中或在 Internet Information Services 內。 此外也會實作 Microsoft.SCIM.IProvider 介面,將類別保存在記憶體中作為範例身分識別存放區。

public class Startup
{
    ...
    public IMonitor MonitoringBehavior { get; set; }
    public IProvider ProviderBehavior { get; set; }

    public Startup(IWebHostEnvironment env, IConfiguration configuration)
    {
        ...
        this.MonitoringBehavior = new ConsoleMonitor();
        this.ProviderBehavior = new InMemoryProvider();
    }
    ...

建置自訂 SCIM 端點

SCIM 端點必須具有 HTTP 位址,而其伺服器驗證憑證的根憑證授權單位是下列其中一個名稱:

  • CNNIC
  • Comodo
  • CyberTrust
  • DigiCert
  • GeoTrust
  • GlobalSign
  • Go Daddy
  • VeriSign
  • WoSign
  • DST Root CA X3

.NET Core SDK 包含可在開發期間使用的 HTTPS 開發憑證,此憑證會在第一次執行期間進行安裝。 ASP.NET Core Web 應用程式根據其執行方式,會接聽不同的連接埠:

  • Microsoft.SCIM.WebHostSample: https://localhost:5001
  • IIS Express: https://localhost:44359

若要進一步了解 ASP.NET Core 中的 HTTPS,請使用下列連結:在 ASP.NET Core 中強制執行 HTTPS

處理端點驗證

來自 Azure AD 佈建服務的要求包括 OAuth 2.0 持有人權杖。 持有人權杖是授權伺服器所發行的安全性權杖,例如 Azure AD,而且受到您的應用程式信任。 您可以將 Azure AD 佈建服務設定為使用下列其中一個權杖:

  • 長時間存留的持有人權杖。 如果 SCIM 端點需要來自非 Azure AD 簽發者的 OAuth 持有人權杖,那麼便將所需的 OAuth 持有人權杖複製到選擇性 [祕密權杖] 欄位。 在開發環境中,您可以使用來自端點的測試 /scim/token 權杖。 測試權杖不應該用於生產環境。

  • Azure AD 持有人權杖。 如果將 [祕密權杖] 欄位保留空白,則 Azure AD 會在每個要求包含從 Azure AD 簽發的 OAuth 持有人權杖。 應用程式若使用 Azure AD 作為識別提供者,便可以驗證此 Azure AD 簽發的權杖。

    • 接收要求的應用程式應該將權杖簽發者驗證為預期的 Azure AD 租用戶的 Azure AD。
    • 在權杖中,會用 iss 宣告來識別簽發者,例如 iss 宣告。 例如: "iss":"https://sts.windows.net/12345678-0000-0000-0000-000000000000/" 。 在此範例中,宣告值的基礎位址 https://sts.windows.net 會將 Azure AD 識別為簽發者,而相對位址區段 12345678-0000-0000-0000-000000000000 則是獲得權杖的 Azure AD 租用戶的唯一識別碼。
    • 權杖的物件是資源庫中應用程式的應用程式識別碼。 在單一租用戶中註冊的應用程式會收到與 SCIM 要求相同的 iss 宣告。 所有自訂應用程式的應用程式識別碼都是 8adf8e6e-67b2-4cf2-a259-e3dc5476c621。 Azure AD 佈建服務所產生的權杖僅供測試之用。 請勿在生產環境中加以使用。

在範例程式碼中,會使用 Microsoft.AspNetCore.Authentication.JwtBearer 套件來驗證要求。 下列程式碼會強制使用 Azure AD 針對指定的租用戶發出的持有人權杖,對任何服務端點的要求進行驗證:

public void ConfigureServices(IServiceCollection services)
{
    if (_env.IsDevelopment())
    {
        ...
    }
    else
    {
        services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        })
            .AddJwtBearer(options =>
            {
                options.Authority = " https://sts.windows.net/12345678-0000-0000-0000-000000000000/";
                options.Audience = "8adf8e6e-67b2-4cf2-a259-e3dc5476c621";
                ...
            });
    }
    ...
}

public void Configure(IApplicationBuilder app)
{
    ...
    app.UseAuthentication();
    app.UseAuthorization();
    ...
}

使用提供的 Postman 測試及使用 localhost 執行本機偵錯時,也必須要有持有人權杖。 範例程式碼會使用 ASP.NET Core 環境在開發階段變更驗證選項,並啟用自我簽署權杖。

如需 ASP.NET Core 中多個環境的詳細資訊,請參閱在 ASP.NET Core 中使用多個環境

下列程式碼會強制使用以自訂金鑰簽署的持有人權杖來驗證對任何服務端點的要求:

public void ConfigureServices(IServiceCollection services)
{
    if (_env.IsDevelopment())
    {
        services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        })
        .AddJwtBearer(options =>
        {
            options.TokenValidationParameters =
                new TokenValidationParameters
                {
                    ValidateIssuer = false,
                    ValidateAudience = false,
                    ValidateLifetime = false,
                    ValidateIssuerSigningKey = false,
                    ValidIssuer = "Microsoft.Security.Bearer",
                    ValidAudience = "Microsoft.Security.Bearer",
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("A1B2C3D4E5F6A1B2C3D4E5F6"))
                };
        });
    }
...

請將 GET 要求傳送至權杖控制器以取得有效的持有人權杖,GenerateJSONWebToken 方法會負責建立與針對開發而設定的參數相符的權杖:

private string GenerateJSONWebToken()
{
    // Create token key
    SymmetricSecurityKey securityKey =
        new SymmetricSecurityKey(Encoding.UTF8.GetBytes("A1B2C3D4E5F6A1B2C3D4E5F6"));
    SigningCredentials credentials =
        new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);

    // Set token expiration
    DateTime startTime = DateTime.UtcNow;
    DateTime expiryTime = startTime.AddMinutes(120);

    // Generate the token
    JwtSecurityToken token =
        new JwtSecurityToken(
            "Microsoft.Security.Bearer",
            "Microsoft.Security.Bearer",
            null,
            notBefore: startTime,
            expires: expiryTime,
            signingCredentials: credentials);

    string result = new JwtSecurityTokenHandler().WriteToken(token);
    return result;
}

處理使用者的佈建和取消佈建

範例 1. 查詢服務中是否有相符的使用者

Azure AD 會查詢服務是否有 externalId 屬性值與 Azure AD 中使用者的 mailNickname 屬性值相符的使用者。 查詢會以類似於此範例的超文字傳輸通訊協定 (HTTP) 要求表示,其中,jyoung 是 Azure AD 中使用者的 mailNickname 範例。

注意

這只是範例。 並非所有使用者都有 mailNickname 屬性,且使用者的值在目錄中可能不是唯一的。 此外,用於比對的屬性 (在此案例中為 externalId) 可在 Azure AD 屬性對應中進行設定。

GET https://.../scim/Users?filter=externalId eq jyoung HTTP/1.1
 Authorization: Bearer ...

在範例程式碼中,要求會轉譯為對服務提供者的 QueryAsync 方法的呼叫。 以下是該方法的簽章:

// System.Threading.Tasks.Tasks is defined in mscorlib.dll.  
// Microsoft.SCIM.IRequest is defined in 
// Microsoft.SCIM.Service.  
// Microsoft.SCIM.Resource is defined in 
// Microsoft.SCIM.Schemas.  
// Microsoft.SCIM.IQueryParameters is defined in 
// Microsoft.SCIM.Protocol.  

Task<Resource[]> QueryAsync(IRequest<IQueryParameters> request);

在範例查詢中,針對具有給定 externalId 屬性值的使用者,傳至 QueryAsync 方法的引數值為:

  • parameters.AlternateFilters.Count:1
  • parameters.AlternateFilters.ElementAt(0).AttributePath: "externalId"
  • parameters.AlternateFilters.ElementAt(0).ComparisonOperator:ComparisonOperator.Equals
  • parameters.AlternateFilter.ElementAt(0).ComparisonValue: "jyoung"

範例 2. 佈建使用者

如果向 SCIM 端點查詢是否有 externalId 屬性值與使用者的 mailNickname 值相符的使用者,但回應未傳回任何使用者,則 Azure AD 會要求服務佈建與 Azure AD 中的使用者對應的使用者。 以下是這類要求的範例:

POST https://.../scim/Users HTTP/1.1
Authorization: Bearer ...
Content-type: application/scim+json
{
   "schemas":
   [
     "urn:ietf:params:scim:schemas:core:2.0:User",
     "urn:ietf:params:scim:schemas:extension:enterprise:2.0User"],
   "externalId":"jyoung",
   "userName":"jyoung@testuser.com",
   "active":true,
   "addresses":null,
   "displayName":"Joy Young",
   "emails": [
     {
       "type":"work",
       "value":"jyoung@Contoso.com",
       "primary":true}],
   "meta": {
     "resourceType":"User"},
    "name":{
     "familyName":"Young",
     "givenName":"Joy"},
   "phoneNumbers":null,
   "preferredLanguage":null,
   "title":null,
   "department":null,
   "manager":null}

在範例程式碼中,要求會轉譯為對服務提供者的 CreateAsync 方法的呼叫。 以下是該方法的簽章:

// System.Threading.Tasks.Tasks is defined in mscorlib.dll.  
// Microsoft.SCIM.IRequest is defined in 
// Microsoft.SCIM.Service.  
// Microsoft.SCIM.Resource is defined in 
// Microsoft.SCIM.Schemas.  

Task<Resource> CreateAsync(IRequest<Resource> request);

在使用者佈建的要求中,資源引數的值會是 Microsoft.SCIM.Core2EnterpriseUser 類別的執行個體 (定義於 Microsoft.SCIM.Schemas 程式庫中)。 如果佈建使用者的要求成功,則方法的實作應會傳回 Microsoft.SCIM.Core2EnterpriseUser 類別的執行個體,並將識別碼屬性的值設定為新佈建之使用者的唯一識別碼。

範例 3.查詢使用者的目前狀態

為了更新已知存在於前端為 SCIM 之身分識別存放區中的使用者,Azure AD 會以類似下方的要求向服務要求該使用者的目前狀態,來繼續執行:

GET ~/scim/Users/54D382A4-2050-4C03-94D1-E769F1D15682 HTTP/1.1
Authorization: Bearer ...

在範例程式碼中,要求會轉譯為對服務提供者的 RetrieveAsync 方法的呼叫。 以下是該方法的簽章:

// System.Threading.Tasks.Tasks is defined in mscorlib.dll.  
// Microsoft.SCIM.IRequest is defined in 
// Microsoft.SCIM.Service.  
// Microsoft.SCIM.Resource and 
// Microsoft.SCIM.IResourceRetrievalParameters 
// are defined in Microsoft.SCIM.Schemas 

Task<Resource> RetrieveAsync(IRequest<IResourceRetrievalParameters> request);

在擷取使用者目前狀態之要求的範例中,提供作為參數引數值的物件具有的屬性值如下所示:

  • 識別碼:"54D382A4-2050-4C03-94D1-E769F1D15682"
  • SchemaIdentifier:urn:ietf:params:scim:schemas:extension:enterprise:2.0:User

範例 4. 查詢要更新的參考屬性值

如果要更新某個參考屬性,Azure AD 就會查詢服務,藉以判斷以該服務作為前端之身分識別存放區中參考屬性目前的值,是否已經與 Azure AD 中該屬性的值相符。 對於使用者,以這種方式可查詢目前值的唯一屬性會是管理員屬性。 下列範例說明要判斷使用者物件的管理員屬性目前是否具有某個值的要求:在範例程式碼中,要求會轉譯為對服務提供者的 QueryAsync 方法的呼叫。 提供物件的屬性值作為參數引數的值,如下所示:

  • parameters.AlternateFilters.Count:2
  • parameters.AlternateFilters.ElementAt(x).AttributePath:「識別碼」
  • parameters.AlternateFilters.ElementAt(x).ComparisonOperator:ComparisonOperator.Equals
  • parameters.AlternateFilter.ElementAt(x).ComparisonValue:"54D382A4-2050-4C03-94D1-E769F1D15682"
  • parameters.AlternateFilters.ElementAt(y).AttributePath: "manager"
  • parameters.AlternateFilters.ElementAt(y).ComparisonOperator:ComparisonOperator.Equals
  • parameters.AlternateFilter.ElementAt(y).ComparisonValue:"2819c223-7f76-453a-919d-413861904646"
  • parameters.RequestedAttributePaths.ElementAt(0):「識別碼」
  • parameters.SchemaIdentifier:urn:ietf:params:scim:schemas:extension:enterprise:2.0:User

索引 x 的值可以是 0,索引 y 的值可以是 1。 或者,x 的值可以是 1,y 的值可以是 0。 這取決於篩選查詢參數的運算式順序。

範例 5. Azure AD 對 SCIM 端點發出要求以更新使用者

這是 Azure AD 對 SCIM 端點發出要求以更新使用者的範例:

PATCH ~/scim/Users/54D382A4-2050-4C03-94D1-E769F1D15682 HTTP/1.1
Authorization: Bearer ...
Content-type: application/scim+json
{
    "schemas": 
    [
      "urn:ietf:params:scim:api:messages:2.0:PatchOp"],
    "Operations":
    [
      {
        "op":"Add",
        "path":"manager",
        "value":
          [
            {
              "$ref":"http://.../scim/Users/2819c223-7f76-453a-919d-413861904646",
              "value":"2819c223-7f76-453a-919d-413861904646"}]}]}

在範例程式碼中,要求會轉譯為對服務提供者的 UpdateAsync 方法的呼叫。 以下是該方法的簽章:

// System.Threading.Tasks.Tasks and 
// System.Collections.Generic.IReadOnlyCollection<T>  // are defined in mscorlib.dll.  
// Microsoft.SCIM.IRequest is defined in
// Microsoft.SCIM.Service.
// Microsoft.SCIM.IPatch, 
// is defined in Microsoft.SCIM.Protocol. 

Task UpdateAsync(IRequest<IPatch> request);

在更新使用者之要求的範例中,提供作為修補程式引數值的物件具有這些屬性值:

引數
ResourceIdentifier.Identifier "54D382A4-2050-4C03-94D1-E769F1D15682"
ResourceIdentifier.SchemaIdentifier urn:ietf:params:scim:schemas:extension:enterprise:2.0:User
(PatchRequest as PatchRequest2).Operations.Count 1
(PatchRequest as PatchRequest2).Operations.ElementAt(0).OperationName OperationName.Add
(PatchRequest as PatchRequest2).Operations.ElementAt(0).Path.AttributePath Manager
(PatchRequest as PatchRequest2).Operations.ElementAt(0).Value.Count 1
(PatchRequest as PatchRequest2).Operations.ElementAt(0).Value.ElementAt(0).Reference http://.../scim/Users/2819c223-7f76-453a-919d-413861904646
(PatchRequest as PatchRequest2).Operations.ElementAt(0).Value.ElementAt(0).Value 2819c223-7f76-453a-919d-413861904646

範例 6. 取消佈建使用者

若要將使用者從前端為 SCIM 端點的身分識別存放區中取消佈建,Azure AD 會傳送如下所示的要求:

DELETE ~/scim/Users/54D382A4-2050-4C03-94D1-E769F1D15682 HTTP/1.1
Authorization: Bearer ...

在範例程式碼中,要求會轉譯為對服務提供者的 DeleteAsync 方法的呼叫。 以下是該方法的簽章:

// System.Threading.Tasks.Tasks is defined in mscorlib.dll.  
// Microsoft.SCIM.IRequest is defined in 
// Microsoft.SCIM.Service.  
// Microsoft.SCIM.IResourceIdentifier, 
// is defined in Microsoft.SCIM.Protocol. 

Task DeleteAsync(IRequest<IResourceIdentifier> request);

提供作為 resourceIdentifier 引數值的物件,在要取消佈建使用者之要求的範例中,會具有這些屬性值:

  • ResourceIdentifier.Identifier:"54D382A4-2050-4C03-94D1-E769F1D15682"
  • ResourceIdentifier.SchemaIdentifier:urn:ietf:params:scim:schemas:extension:enterprise:2.0:User

整合 SCIM 端點與 Azure AD 佈建服務

Azure AD 可設定為將已指派的使用者和群組自動佈建至實作 SCIM 2.0 通訊協定之特定設定檔的應用程式。 設定檔的詳細資訊記載於了解 Azure AD SCIM 實作

洽詢應用程式提供者,或參閱應用程式提供者文件中的相關陳述,以了解是否符合這些需求。

重要

Azure AD SCIM 實作建置於 Azure AD 使用者佈建服務之上,其設計目的是要讓使用者在 Azure AD 與目標應用程式之間保持同步,並實作一組非常明確的標準作業。 請務必了解這些行為,以了解 Azure AD 佈建服務的行為。 如需詳細資訊,請參閱佈建週期:初始和增量一節 (位於佈建運作方式中)。

開始使用

支援本文所述 SCIM 設定檔的應用程式,可使用 Azure AD 應用程式庫中的「不在資源庫內的應用程式」功能連線到 Azure AD。 連線之後,Azure AD 會每隔 40 分鐘執行一次同步處理程序,此程序會為指派的使用者和群組查詢應用程式的 SCIM 端點,並根據指派詳細資料加以建立或修改。

若要連接支援 SCIM 的應用程式:

  1. 登入 AD Azure 入口網站。 您可以註冊開發人員計劃,藉以取得具有 P2 授權的 Azure AD 免費試用版

  2. 在左側窗格中,選取 [企業應用程式]。 此時會顯示所有已設定的應用程式清單,包括已從資源庫新增的應用程式。

  3. 選取 [+ 新增應用程式] > [+ 建立您自己的應用程式]。

  4. 輸入應用程式的名稱,並選擇 [整合您在資源庫中找不到的其他任何應用程式] 選項,然後選取 [新增] 以建立應用程式物件。 新的應用程式會新增至企業應用程式清單,並在開啟後進入其應用程式管理畫面。

    下圖顯示 Azure AD 應用程式庫的螢幕擷取畫面:

    顯示 Azure AD 應用程式庫的螢幕擷取畫面。

    注意

    如果您要使用舊的應用程式庫體驗,則請遵循下面的螢幕指南。

    下列螢幕擷取畫面顯示 Azure AD 舊應用程式庫體驗:

    顯示 Azure AD 舊應用程式庫體驗的螢幕擷取畫面

  5. 在應用程式管理畫面中,選取左側面板中的 [佈建]。

  6. 在 [佈建模式] 功能表上,選取 [自動]。

    以下螢幕擷取畫面顯示在 Azure 入口網站中進行佈建設定:

    1 螢幕擷取畫面:Azure 入口網站中的應用程式佈建頁面。

  7. 在 [租用戶 URL] 欄位中,輸入應用程式 SCIM 端點的 URL。 範例: https://api.contoso.com/scim/

  8. 如果 SCIM 端點需要來自非 Azure AD 簽發者的 OAuth 持有人權杖,那麼便將所需的 OAuth 持有人權杖複製到選擇性 [祕密權杖] 欄位。 如果將此欄位保留空白,則 Azure AD 會在每個要求包含從 Azure AD 簽發的 OAuth 持有人權杖。 應用程式若使用 Azure AD 作為識別提供者,便可以驗證此 Azure AD 簽發的權杖。

    注意

    「不」建議將此欄位空白並依賴 Azure AD 所產生的權杖。 此選項主要供測試之用。

  9. 選取 [測試連線],讓 Azure AD 嘗試連線至 SCIM 端點。 如果嘗試失敗,將會顯示錯誤資訊。

    注意

    [測試連線] 會查詢 SCIM 端點中是否有不存在的使用者,並使用隨機 GUID 作為 Azure AD 設定中選取的比對屬性。 預期的正確回應是 HTTP 200 OK 和空白的 SCIM ListResponse 訊息。

  10. 如果嘗試連線至應用程式成功,請選取 [儲存] 以儲存管理員認證。

  11. 在 [對應] 區段中,有兩組可選取的屬性對應:一個用於使用者物件,一個用於群組物件。 選取其中一個以檢閱從 Azure AD 同步處理至應用程式的屬性。 選取為 [比對] 屬性的屬性會用來比對應用程式中的使用者和群組以進行更新作業。 選取 [儲存] 認可任何變更。

    注意

    您可以選擇性地藉由停用「群組」對應以停用同步處理群組物件。

  12. 在 [設定] 底下,[範圍] 欄位會定義要同步的使用者和群組。 選取 [僅同步處理指派的使用者和群組] (建議選項),僅同步處理 [使用者和群組] 索引標籤中指派的使用者和群組。

  13. 設定完成後,請將 [佈建狀態] 設定為 [開啟]。

  14. 選取 [儲存] 以啟動 Azure AD 佈建服務。

  15. 如果僅同步處理指派的使用者和群組 (建議選項),請選取 [使用者和群組] 索引標籤。然後,指派您要同步處理的使用者或群組。

初始週期開始後,您可以在左側面板中選取 [佈建記錄] 以監視進度,其中會顯示佈建服務對您的應用程式執行的所有動作。 如需如何讀取 Azure AD 佈建記錄的詳細資訊,請參閱關於使用者帳戶自動佈建的報告

注意

初始週期執行時會比後續的同步處理耗時;在服務執行期間,大約每 40 分鐘會執行一次同步處理。

如果您要建立將由多個租用戶使用的應用程式,您可以在 Azure AD 應用程式庫中加以提供。 組織能夠輕鬆地探索應用程式和設定佈建。 在 Azure AD 資源庫中發佈您的應用程式並供其他人佈建,是很簡單的作業。 請在 這裡查明步驟。 Microsoft 會與您合作,將您的應用程式整合到我們的資源庫中、測試您的端點,以及發行上線文件供客戶使用。

使用檢查清單快速讓您的應用程式上線,並讓客戶擁有順暢的部署體驗。 當您上線至資源庫時,系統將會向您收集資訊。

  • 支援 SCIM 2.0 使用者和群組端點 (只需要一個,但建議兩者都使用)
  • 每個租用戶每秒支援至少 25 個要求,以確保在沒有延遲的情況下佈建和取消佈建使用者和群組 (必要)
  • 建立工程和支援連絡人,以便在資源庫上線後引導客戶 (必要)
  • 應用程式有 3 個未過期的測試認證可使用 (必要)
  • 支援 OAuth 授權碼授與或長時間存留的權杖,如下所述 (必要)
  • 建立工程和支援連絡點,以便在資源庫上線後支援客戶 (必要)
  • 支援結構描述探索 (必要)
  • 支援使用單一 PATCH 更新多個群組成員資格
  • 公開記載您的 SCIM 端點

SCIM 規格並未定義 SCIM 特有的驗證和授權機制,並且依賴現有產業標準的使用。

授權方法 優點 缺點 支援
使用者名稱和密碼 (Azure AD 不建議使用或加以支援) 易於實作 不安全 - 您的 Pa$$word 無關緊要 新的資源庫或非資源庫應用程式不予支援。
長時間存留的持有人權杖 長時間存留的權杖不需要有使用者存在。 在設定佈建時,管理員很容易就能使用這些權杖。 若未使用不安全的方法 (例如電子郵件),長時間存留的權杖可能難以與管理員共用。 支援資源庫和非資源庫應用程式。
OAuth 授權碼授與 存取權杖的存留期遠比密碼短,且具有長期持有人權杖所沒有的自動化重新整理機制。 在初始授權期間必須有實際的使用者存在,因而增加了一層責任。 必須要有使用者存在。 如果使用者離職,權杖就會失效,而必須重新完成授權。 支援資源庫應用程式,但不支援非資源庫應用程式。 不過,您可以在 UI 中提供存取權杖,做為短期測試用途的秘密權杖。 除了支援資源庫應用程式上的可設定驗證/權杖 URL 之外,待辦項目還支援針對非資源庫的 OAuth 代碼授與。
OAuth 用戶端認證授與 存取權杖的存留期遠比密碼短,且具有長期持有人權杖所沒有的自動化重新整理機制。 授權碼授與和用戶端認證授與會建立相同類型的存取權杖,因此,這些方法的切換對 API 而言是透明的。 佈建可以自動化,且可以無訊息方式要求新的權杖,而不需要使用者介入。 支援資源庫應用程式,但不支援非資源庫應用程式。 不過,您可以在 UI 中提供存取權杖,做為短期測試用途的秘密權杖。 支援非資源庫上的 OAuth 用戶端認證授與是我們的待辦項目。

注意

不建議您在 Azure AD 佈建設定自訂應用程式 UI 中將 [權杖] 欄位保留為空白。 產生的權杖主要供測試之用。

OAuth 代碼授與流程

佈建服務支援授權碼授與,而且,提交您在資源庫中發佈應用程式的要求之後,我們的小組會與您一起收集下列資訊:

  • 授權 URL:用戶端透過使用者代理程式重新導向對資源擁有者取得授權時所使用的 URL。 使用者會重新導向至此 URL 以授與存取權。

  • 權杖交換 URL:用戶端用來交換存取權杖的授權的 URL (通常是使用用戶端驗證)。

  • 用戶端識別碼:授權伺服器會向已註冊的用戶端發出用戶端識別碼,而這個唯一字串代表用戶端所提供的註冊資訊。 用戶端識別碼不是祕密,而會向資源擁有者公開,且不得單獨用於用戶端驗證。

  • 用戶端祕密:授權伺服器所產生的祕密,而這應該是只有授權伺服器才知道的唯一值。

注意

目前無法針對每個租用戶設定 [授權 URL] 和 [權杖交換 URL]。

注意

因為用戶端祕密曝光,所以不支援 OAuth v1。 OAuth v2 則受支援。

最佳做法 (建議,但非必要):

  • 支援多個重新導向 URL。 管理員可從 "portal.azure.com" 和 "aad.portal.azure.com" 設定佈建。 支援多個重新導向 URL 可確保使用者可從任一入口網站授與存取權。
  • 支援多個祕密以方便續約,而不需要停機。

如何設定 OAuth 代碼授與流程

  1. 登入 Azure 入口網站,並移至 [Enterprise 應用程式] > [應用程式] > [佈建],然後選取 [授權]。

    1. Azure 入口網站會將使用者重新導向至授權 URL (第三方應用程式的登入頁面)。

    2. 管理員會提供認證給第三方應用程式。

    3. 第三方應用程式會將使用者重新導向回到 Azure 入口網站並提供授權碼

    4. Azure AD 佈建服務會呼叫權杖 URL,並提供授權碼。 第三方應用程式會以存取權杖、重新整理權杖和到期日回應

  2. 當佈建週期開始時,服務會檢查目前的存取權杖是否有效,並視需要將其與新的權杖交換。 存取權杖會在對應用程式提出的每個要求中提供,而且會在提出每個要求之前檢查要求的有效性。

注意

儘管目前無法在非資源庫應用程式上設定 OAuth,但是您可以從授權伺服器手動產生存取權杖,並將它輸入為非資源庫應用程式的祕密權杖。 這可讓您在登入應用程式資源庫之前,驗證 SCIM 伺服器與 Azure AD 佈建服務的相容性,以支援 OAuth 驗證碼授與。

長時間存留的 OAuth 持有人權杖:如果您的應用程式不支援 OAuth 授權碼授與流程,則您也可以產生長時間存留的 OAuth 持有人權杖,而管理員可用它來設定佈建整合。 此權杖應該是永久的,否則,當權杖過期時,佈建作業將遭到隔離

如需其他驗證和授權方法的相關資訊,請在 UserVoice 上告訴我們。

為了協助您了解我們的聯合整合並帶動其需求,建議您更新現有的建,並在您的行銷通路中詳細說明此整合。 建議您完成下列檢查清單以支援啟動:

  • 請確定您的銷售和客戶支援小組熟知整合功能,且有能力加以宣傳。 對您的小組進行簡報,為其提供常見問題集,並將整合納入您的銷售資料中。
  • 製作一篇部落格文章或新聞稿,說明聯合整合的性質、優點,以及如何開始使用。 範例:Imprivata 和 Azure AD 新聞稿
  • 利用您的社交媒體 (例如 Twitter、Facebook 或 LinkedIn),向您的客戶推廣整合。 請務必納入 @AzureAD,好讓我們轉推您的貼文。 範例:Imprivata Twitter 貼文
  • 建立或更新您的行銷頁面/網站 (例如整合頁面、合作夥伴頁面、定價頁面等),將聯合整合的可用性納入其中。 範例:Pingboard 整合頁面Smartsheet 整合頁面Monday.com 定價頁面
  • 撰寫說明中心文章或技術文件,向客戶解說應從何著手。 範例:Envoy + Microsoft Azure AD 整合。
  • 透過您的客戶通訊 (每月電子報、電子郵件行銷活動、產品版本資訊),提醒客戶有新的整合。

後續步驟