分享方式:


針對企業應用程式自定義 JSON Web 令牌 (JWT) 中發出的宣告

Microsoft 身分識別平台 支援單一登錄(SSO),其中包含Microsoft Entra 應用連結庫和自定義應用程式中大部分預先整合的應用程式。 當使用者使用 OIDC 通訊協定透過 Microsoft 身分識別平台 向應用程式進行驗證時,會將令牌傳送至應用程式。 應用程式會驗證並使用權杖將使用者登入,而不會提示輸入使用者名稱和密碼。

OIDC 和 OAuth 應用程式所使用的這些 JSON Web 令牌(JWT)包含使用者稱為 宣告的資訊片段。 宣告是識別提供者在發給使用者的權杖內用以描述使用者的資訊。 在 OIDC 回應中,宣告數據通常會包含在識別提供者以 JWT 形式發出的識別元令牌中。

檢視或編輯宣告

提示

根據您開始的入口網站,本文中的步驟可能略有不同。

若要檢視或編輯 JWT 中對應用程式發出的宣告:

  1. 以至少 雲端應用程式系統管理員 的身分登入 Microsoft Entra 系統管理中心
  2. 瀏覽至 [身分識別]>[應用程式]>[企業應用程式]>[所有應用程式]
  3. 選取應用程式,選取左側功能表中的 [單一登入],然後在 [屬性與宣告] 區段中選取 [編輯]

由於各種原因,應用程式可能需要宣告自定義。 例如,當應用程式需要一組不同的宣告 URI 或宣告值時。 使用 [屬性與宣告] 區段,您可以新增或移除應用程式的宣告。 您也可以根據使用案例,建立應用程式特有的自定義宣告。

下列步驟說明如何指派常數值:

  1. 選取您要修改的宣告。
  2. 根據您的組織輸入Source屬性中不含引號的常數值,然後選取 [儲存]。

[屬性] 概觀會顯示常數值。

特殊宣告轉換

您可以使用下列特殊宣告轉換函式。

函式 描述
ExtractMailPrefix() 從電子郵件地址或使用者主體名稱中移除網域尾碼。 此函式只會擷取用戶名稱的第一個部分。 例如,joe_smith 而不是 joe_smith@contoso.com
ToLower() 將所選取屬性中的字元轉換成小寫字元。
ToUpper() 將所選取屬性中的字元轉換成大寫字元。

新增應用程式特定宣告

若要新增應用程式特定宣告:

  1. [使用者屬性和宣告] 中,選取 [ 新增宣告 ] 以開啟 [ 管理使用者宣告 ] 頁面。
  2. 輸入宣告的 [名稱]。 值不需要遵循 URI 模式。 如果您需要 URI 模式,您可以將該 模式放在 [命名空間 ] 字段中。
  3. 選取宣告要擷取其值的來源。 您可以使用來源屬性下拉式選單中的屬性,或對使用者屬性套用轉換再發出為宣告。

宣告轉換

若要將轉換套用到使用者屬性:

  1. 在 [管理宣告] 中,選取 [轉換] 作為宣告來源以開啟 [管理轉換] 頁面。
  2. 從轉換下拉式清單選取函式。 視所選取的函式而定,提供參數與常數值以在轉換中進行評估。
  3. 將來源視為多重值 ,指出轉換是套用至所有值,還是只套用到第一個值。 根據預設,多重值宣告中的第一個專案會套用轉換。 當您核取此方塊時,可確保它已套用至全部。 此複選框僅針對多重值屬性啟用。 例如: user.proxyaddresses
  4. 若要套用多個轉換,請選取 [新增轉換]。 您最多可以將兩個轉換套用至宣告。 例如,您可以先擷取 user.mail 的電子郵件前置詞。 接著將字串設定為大寫。

您可以使用下列函式來轉換宣告。

函式 描述
ExtractMailPrefix() 從電子郵件地址或使用者主體名稱中移除網域尾碼。 此函式只會擷取用戶名稱的第一個部分。 例如,joe_smith 而不是 joe_smith@contoso.com
Join() 透過聯結兩個屬性來建立新值。 您也可以選擇性地在兩個屬性之間使用分隔符號。 針對 NameID 宣告轉換,Join() 函式在轉換輸入具有定義域部分時具有特定行為。 該函式會先從輸入中移除網域部分,再將其與分隔符號和選取的參數聯結。 例如,如果轉換的輸入是 joe_smith@contoso.com,分隔符號是 @,而參數是 fabrikam.com,則此輸入組合會產生 joe_smith@fabrikam.com
ToLowercase() 將所選取屬性中的字元轉換成小寫字元。
ToUppercase() 將所選取屬性中的字元轉換成大寫字元。
Contains() 如果輸入符合指定的值,則輸出屬性或常數。 否則,您可以在沒有相符結果時指定另一個輸出。
例如,假設您想要發出宣告,其中如果值包含網域 @contoso.com,便代表其為使用者的電子郵件地址,否則您便想要輸出使用者主體名稱。 若要執行此函式,您可以設定下列值:
參數 1(輸入):user.email
:“@contoso.com”
參數 2 (輸出):user.email
參數 3 (如果沒有相符的輸出):user.userprincipalname
EndWith() 如果輸入的結尾是指定的值,則輸出屬性或常數。 否則,您可以在沒有相符結果時指定另一個輸出。
例如,假設您想要發出宣告,其中如果員工識別碼是以 000 作為結尾,便代表值為使用者的員工識別碼,否則您便想要輸出擴充屬性。 若要執行此函式,您可以設定下列值:
參數 1(input):user.employeeid
:“000”
參數 2 (輸出):user.employeeid
參數 3 (如果沒有相符的輸出):user.extensionattribute1
StartWith() 如果輸入的開頭是指定的值,則輸出屬性或常數。 否則,您可以在沒有相符結果時指定另一個輸出。
例如,假設您想要發出宣告,其中如果國家/地區是以 US 作為開頭,便代表值為使用者的員工識別碼,否則您便想要輸出擴充屬性。 若要執行此函式,您可以設定下列值:
參數 1(input):user.country
:“US”
參數 2 (輸出):user.employeeid
參數 3 (如果沒有相符的輸出):user.extensionattribute1
Extract() - 比對之後 在子字串符合指定值之後加以傳回。
例如,假設輸入的值是 Finance_BSimon,相符的值是 Finance_,則宣告的輸出便是 BSimon
Extract() - 比對之前 傳回子字串,直到其符合指定值為止。
例如,假設輸入的值是 BSimon_US,相符的值是 _US,則宣告的輸出便是 BSimon
Extract() - 比對之間 傳回子字串,直到其符合指定值為止。
例如,假設輸入的值是 Finance_BSimon_US,第一個相符的值是 Finance_,第二個相符的值是 _US,則宣告的輸出便是 BSimon
ExtractAlpha() - 前置詞 傳回字串的前置詞字母部分。
例如,假設輸入的值是 BSimon_123,其便會傳回 BSimon
ExtractAlpha() - 後置詞 傳回字串的後置詞字母部分。
例如,假設輸入的值是 123_Simon,其便會傳回 Simon
ExtractNumeric() - 前置詞 傳回字串的前置詞數值部分。
例如,假設輸入的值是 123_BSimon,其便會傳回 123
ExtractNumeric() - 後置詞 傳回字串的後置詞數值部分。
例如,假設輸入的值是 BSimon_123,其便會傳回 123
IfEmpty() 如果輸入為 Null 或空白,則輸出屬性或常數。
例如,如果您想要輸出儲存在擴充屬性中的屬性,如果指定使用者的員工標識碼是空的。 若要執行此函式,請設定下列值:
參數 1(input): user.employeeid
參數 2 (輸出):user.extensionattribute1
參數 3 (如果沒有相符的輸出):user.employeeid
IfNotEmpty() 如果輸入為 Null 或空白,則輸出屬性或常數。
例如,如果您想要輸出儲存在擴充屬性中的屬性,如果指定使用者的員工標識碼不是空的。 若要執行此函式,您可以設定下列值:
參數 1(input): user.employeeid
參數 2 (輸出):user.extensionattribute1
Substring() - 固定長度 從指定位置的字元開始擷取部分的字串宣告類型,並傳回指定數目的字元。
SourceClaim - 應該執行的轉換宣告來源。
StartIndex - 這個實例中子字串以零起始的起始字元位置。
Length - 子字串的字元長度。
例如:
sourceClaim - PleaseExtractThisNow
StartIndex - 6
長度 - 11
輸出:ExtractThis
Substring() - EndOfString 從指定位置的字元開始擷取部分的字串宣告類型,並從指定的起始索引傳回其餘的宣告部分。
SourceClaim - 轉換的宣告來源。
StartIndex - 這個實例中子字串以零起始的起始字元位置。
例如:
sourceClaim - PleaseExtractThisNow
StartIndex - 6
輸出:ExtractThisNow
RegexReplace() RegexReplace() 轉換接受做為輸入參數:
- 參數 1:使用者屬性作為 regex 輸入
- 信任來源為多重值的選項
- Regex 模式
- 取代模式。 取代模式可能包含靜態文字格式,以及指向 regex 輸出群組和更多輸入參數的參考。

如果您需要其他轉換,請在意見反應論壇中,在 SaaS 應用程式類別下Microsoft Entra ID 提交您的想法。

RegEx 型宣告轉換

下圖顯示第一層轉換的範例:

第一層轉換的螢幕擷取畫面。

下表提供第一層轉換的相關信息。 下表中所列的動作會對應至上圖中的標籤。 選取 [編輯] 以開啟宣告轉換刀鋒視窗。

動作 欄位 描述
1 Transformation 從 [轉換] 選項中選取 [RegexReplace()] 選項,以使用 RegEx 型宣告轉換方法進行宣告轉換。
2 Parameter 1 規則運算式轉換的輸入。 例如,具有 admin@fabrikam.com 等使用者電子郵件地址的 user.mail。
3 Treat source as multivalued 某些輸入使用者屬性可以是多重值使用者屬性。 如果選取的使用者屬性支援多個值,而且使用者想要使用多個值進行轉換,則必須選取 [將來源視為多重值]。 如果已選取,則會使用所有值進行 RegEx 比對,否則只會使用第一個值。
4 Regex pattern 根據選取為 [參數 1] 的使用者屬性值進行評估的規則運算式。 例如,從使用者的電子郵件地址擷取使用者別名的正規表示式會表示為 (?'domain'^.*?)(?i)(\@fabrikam\.com)$
5 Add additional parameter 可使用多個使用者屬性進行轉換。 屬性的值則會與 RegEx 轉換輸出合併。 最多支援五個參數。
6 Replacement pattern 取代模式是文字範本,其中包含 RegEx 結果的預留位置。 所有組名都必須包裝在大括弧內,例如 {group-name}。 假設系統管理員想要一併使用使用者別名及某些其他網域名稱 (例如 xyz.com),並與國家/地區名稱加以合併。 在本案例中,取代模式會是 {country}.{domain}@xyz.com,其中 {country} 是輸入參數的值,而 {domain} 是規則運算式評估中的群組輸出。 在這種情況下,預期的結果是 US.swmal@xyz.com

下圖顯示第二層轉換的範例:

第二層宣告轉換的螢幕擷取畫面。

下表提供有關第二層轉換的資訊。 下表中所列的動作會對應至上圖中的標籤。

動作 欄位 描述
1 Transformation RegEx 型宣告轉換不限制於第一層轉換,也可以用來作為第二層轉換。 任何其他轉換方法都可以作為第一層轉換。
2 Parameter 1 如果選取 RegexReplace() 作為第二層轉換,則第一層轉換的輸出會作為第二層轉換的輸入。 若要套用轉換,第二層 RegEx 運算式應該符合第一層轉換的輸出。
3 Regex pattern [RegEx 模式] 是第二層轉換的規則運算式。
4 Parameter input 第二層轉換的使用者屬性輸入。
5 Parameter input 如果系統管理員不再需要選取的輸入參數,則可以將其刪除。
6 Replacement pattern 取代模式是文字範本,其中包含 RegEx 結果群組名稱的預留位置、輸入參數群組名稱的預留位置和靜態文字值的預留位置。 所有群組名稱都必須以大括弧括住,例如 {group-name}。 假設系統管理員想要一併使用使用者別名及某些其他網域名稱 (例如 xyz.com),並與國家/地區名稱加以合併。 在本案例中,取代模式會是 {country}.{domain}@xyz.com,其中 {country} 是輸入參數的值,而 {domain} 是規則運算式評估中的群組輸出。 在這種情況下,預期的結果是 US.swmal@xyz.com
7 Test transformation 只有在 [參數 1] 的選取使用者屬性值符合 [RegEx 模式] 文字方塊中提供的規則運算式時,才會評估 RegexReplace() 轉換。 如果不符合,預設宣告值會新增至權杖。 若要根據輸入參數值驗證規則運算式,則可在 [轉換] 刀鋒視窗中使用測試體驗。 此測試體驗僅適用於虛擬值。 使用更多輸入參數時,參數的名稱會新增至測試結果,而不是實際值。 若要存取測試區段,請選擇 [測試轉換]

下圖顯示測試轉換的範例:

測試轉換的螢幕擷取畫面。

下表提供有關測試轉換的資訊。 下表中所列的動作會對應至上圖中的標籤。

動作 欄位 描述
1 Test transformation 選取 [關閉] 或 (X) 按鈕以隱藏測試區段,再次於刀鋒視窗上重新顯示 [測試轉換] 按鈕。
2 Test regex input 接受用於規則運算式測試評估的輸入。 如果 RegEx 型宣告轉換設定為第二層轉換,請提供第一層轉換的預期輸出值。
3 Run test 提供測試 RegEx 輸入並設定 [RegEx 模式]、[取代模式] 和 [輸入參數] 之後,即可選取 [執行測試] 來評估運算式。
4 Test transformation result 如果評估成功,則會根據 [測試轉換結果] 標籤轉譯測試轉換的輸出。
5 Remove transformation 選取 [移除轉換] 可移除第二層轉換。
6 Specify output if no match 如果已根據 [參數 1] 設定 RegEx 輸入值,但與 [規則運算式] 不符,則會略過轉換。 在這種情況下,可設定替代使用者屬性,這會藉由核取 [如果沒有相符項目,則指定輸出],將其新增至宣告的權杖。
7 Parameter 3 當沒有相符項目且核取了 [如果沒有相符項目,則指定輸出] 時,如果必須傳回替代使用者屬性,則可以使用此下拉式清單選取替代使用者屬性。 此下拉式清單是針對 [參數 3 (如果沒有相符項目的輸出)] 所提供。
8 Summary 在刀鋒視窗底部,會顯示格式的完整摘要,簡單說明轉換的意義。
9 Add 驗證轉換的組態設定之後,即可選取 [新增],將其儲存至宣告原則。 在 [管理宣告] 刀鋒視窗上選取 [儲存],以儲存變更。

RegexReplace() 轉換也適用於群組宣告轉換。

轉換驗證

選取 [新增] 或 [執行測試] 之後發生下列情況時,訊息會提供詳細資訊:

  • 使用了具有重複使用者屬性的輸入參數。
  • 找到未使用的輸入參數。 已定義的輸入參數應該具有取代模式文字的個別用法。
  • 提供的測試 RegEx 輸入與提供的規則運算式不符。
  • 找不到取代模式中群組的來源。

根據條件發出宣告

您可以根據使用者類型和使用者所屬的群組來指定宣告的來源。

使用者類型可以是:

  • 任何 - 所有使用者都可以存取應用程式。
  • 成員: 租用戶的原生成員
  • 所有來賓:使用者已從具有或沒有Microsoft Entra標識碼的外部組織移動。
  • Microsoft Entra 來賓: 來賓使用者屬於使用 Microsoft Entra ID 的另一個組織。
  • 外部來賓: 來賓使用者屬於沒有 Microsoft Entra ID 的外部組織。

例如,當宣告的來源對於存取應用程式的來賓和員工而言不同時,使用者類型會很有幫助。 您可以指定如果使用者是員工,請從 user.email 取得 NameID。 如果使用者是來賓,則 NameID 來自 user.extensionattribute1。

若要新增宣告條件:

  1. 在 [管理宣告] 中,展開 [宣告條件]。
  2. 選取使用者類型。
  3. 選取該使用者應隸屬的群組。 針對指定應用程式,您在所有宣告上最多可以選取 50 個唯一群組。
  4. 選取宣告要擷取其值的來源。 您可以使用來源屬性下拉式選單中的屬性,或對使用者屬性套用轉換再發出為宣告。

您新增條件的順序很重要。 Microsoft Entra 會先以來源 Attribute 評估所有條件,然後以來源 Transformation 評估所有條件,以決定要在宣告中發出哪個值。 Microsoft Entra ID 會從上到下評估具有相同來源的條件。 宣告會發出符合宣告中表達式的最後一個值。 轉換 (例如 IsNotEmptyContains) 的行為類似於限制。

例如,Britta Simon 是 Contoso 租用戶中的來賓使用者。 Britta 隸屬同樣也使用 Microsoft Entra ID 的另一個組織。 在針對 Fabrikam 應用程式套用下列設定的情況下,當 Britta 嘗試登入 Fabrikam 時,Microsoft 身分識別平台會評估條件。

首先,Microsoft 身分識別平台會驗證 Britta 的使用者類型是否為 [所有來賓]。 因為類型為 [所有來賓],Microsoft 身分識別平台會將宣告的來源指派給 user.extensionattribute1。 其次,Microsoft 身分識別平台會驗證 Britta 的使用者類型是否為 [Microsoft Entra 來賓]。 因為類型為 [所有來賓],Microsoft 身分識別平台會將宣告的來源指派給 user.mail。 最後,系統會針對 Britta 使用 user.mail 值發出宣告。

另一個範例是,請考慮 Britta Simon 嘗試使用下列設定登入時。 Microsoft Entra 會先評估來源 Attribute的所有條件。 宣告的來源是 user.mail Britta 的用戶類型 Microsoft Entra 來賓時。 接下來,Microsoft Entra ID 會評估轉換。 因為 Britta 是來賓, user.extensionattribute1 因此是宣告的新來源。 因為 Britta 位於 Microsoft Entra 來賓user.othermail因此是此宣告的新來源。 最後,系統會針對 Britta 使用 user.othermail 值發出宣告。

最後一個範例是,考慮假設 Britta 尚未設定 user.othermail 或其為空白時,會發生什麼事。 宣告會回復為 user.extensionattribute1 忽略這兩種情況下的條件專案。

安全性考量

接收令牌的應用程式依賴無法竄改的宣告值。 當您透過宣告自定義來修改令牌內容時,這些假設可能不再正確。 應用程式必須明確確認已修改令牌,以保護自己免於惡意執行者所建立的自定義。 以下列其中一種方式保護不適當的自定義:

如果沒有,Microsoft Entra ID 會傳 回AADSTS50146錯誤碼

設定自訂簽署金鑰

針對多租使用者應用程式,應該使用自定義簽署密鑰。 請勿在應用程式指令清單中設定 acceptMappedClaims 。 在 Azure 入口網站 中設定應用程式時,您會在租使用者中取得應用程式註冊對象和服務主體。 該應用程式使用 Azure 全域登入金鑰,無法用於自定義令牌中的宣告。 若要在令牌中取得自定義宣告,請從憑證建立自定義登入密鑰,並將其新增至服務主體。 如果要進行測試,您可以使用自我簽署憑證。 設定自訂簽署金鑰之後,您的應用程式程式代碼必須驗證令牌簽署金鑰。

將下列資訊新增至服務主體:

  • 私密金鑰認證
  • 密碼 (作為 密碼認證
  • 公開金鑰認證

從憑證的 PFX 檔案匯出擷取以編碼的私鑰和公鑰 base-64。 請確定 keyId keyCredential 用於 「Sign」 的 符合 keyIdpasswordCredential。 您可以藉由取得憑證指紋的哈希來產生 customkeyIdentifier

Request

注意

請先從 [Microsoft Entra 系統管理中心應用程式註冊] 刀鋒視窗停用新建立的應用程式上的任何 服務主體鎖定 設定,再嘗試在服務主體上執行 PATCH,導致 400 不正確的要求。

下列範例顯示 HTTP PATCH 要求的格式,以將自訂簽署密鑰新增至服務主體。 屬性中的 keyCredentials 「索引鍵」值會縮短為可讀性。 值為base-64編碼。 對於私鑰,屬性使用方式為 Sign。 對於公鑰,屬性使用方式為 Verify

PATCH https://graph.microsoft.com/v1.0/servicePrincipals/aaaaaaaa-bbbb-cccc-1111-222222222222

Content-type: servicePrincipals/json
Authorization: Bearer {token}

{
    "keyCredentials":[
        {
            "customKeyIdentifier": "aB1cD2eF3gH4iJ5kL6-mN7oP8qR=", 
            "endDateTime": "2021-04-22T22:10:13Z",
            "keyId": "aaaaaaaa-0b0b-1c1c-2d2d-333333333333",
            "startDateTime": "2020-04-22T21:50:13Z",
            "type": "X509CertAndPassword",
            "usage": "Sign",
            "key":"cD2eF3gH4iJ5kL6mN7-oP8qR9sT==",
            "displayName": "CN=contoso"
        },
        {
            "customKeyIdentifier": "aB1cD2eF3gH4iJ5kL6-mN7oP8qR=",
            "endDateTime": "2021-04-22T22:10:13Z",
            "keyId": "bbbbbbbb-1c1c-2d2d-3e3e-444444444444",
            "startDateTime": "2020-04-22T21:50:13Z",
            "type": "AsymmetricX509Cert",
            "usage": "Verify",
            "key": "cD2eF3gH4iJ5kL6mN7-oP8qR9sT==",
            "displayName": "CN=contoso"
        }

    ],
    "passwordCredentials": [
        {
            "customKeyIdentifier": "aB1cD2eF3gH4iJ5kL6-mN7oP8qR=",
            "keyId": "cccccccc-2d2d-3e3e-4f4f-555555555555",
            "endDateTime": "2022-01-27T19:40:33Z",
            "startDateTime": "2020-04-20T19:40:33Z",
            "secretText": "mypassword"
        }
    ]
}

使用 PowerShell 設定自訂簽署金鑰

使用 PowerShell 具 現化 MSAL 公用用戶端應用程式 ,並使用 授權碼授 與流程來取得 Microsoft Graph 的委派許可權存取令牌。 使用存取令牌來呼叫 Microsoft Graph,並設定服務主體的自定義簽署密鑰。 設定自訂簽署金鑰之後,您的應用程式程式代碼必須 驗證令牌簽署金鑰

若要執行此文稿,您需要:

  • 應用程式服務主體的物件標識碼,位於 Azure 入口網站 中應用程式專案 [概觀] 刀鋒視窗中的應用程式專案。
  • 應用程式註冊以登入使用者,並取得存取令牌以呼叫 Microsoft Graph。 在 Azure 入口網站 中應用程式專案 應用程式註冊 的 [概觀] 刀鋒視窗中,取得此應用程式的應用程式(用戶端)標識符。 應用程式註冊應該具有下列設定:
    • “; 的http://localhost"重新導向 URI;列在行動 裝置和傳統型應用程式 平台組態中。
    • API 許可權中,Microsoft Graph 委派的許可權 Application.ReadWrite.AllUser.Read (請務必授與系統管理員同意這些許可權)。
  • 登入以取得 Microsoft Graph 存取令牌的使用者。 用戶應該是下列其中一個Microsoft Entra 系統管理角色(需要更新服務主體):
    • 雲端應用程式系統管理員
    • 應用程式系統管理員
  • 要設定為應用程式自定義簽署金鑰的憑證。 您可以建立自我簽署憑證,或從信任的證書頒發機構單位取得憑證。 文稿中會使用下列憑證元件:
    • 公鑰(通常是 .cer 檔案)
    • PKCS#12 格式的私鑰(在 .pfx 檔案中
    • 私密密碼 (.pfx 檔案)

重要

私鑰必須是 PKCS#12 格式,因為 Microsoft Entra ID 不支援其他格式類型。 使用錯誤的格式可能會導致錯誤「憑證無效:金鑰值無效憑證」,當使用 Microsoft Graph 來修補包含 keyCredentials 憑證資訊的 服務主體時。

##########################################################
# Replace the variables below with the appropriate values 

$fqdn="yourDomainHere" # This is used for the 'issued to' and 'issued by' field of the certificate
$pwd="password" # password for exporting the certificate private key
$tenantId   = "aaaabbbb-0000-cccc-1111-dddd2222eeee" # Replace with your Tenant ID
$appObjId = "aaaaaaaa-0000-1111-2222-bbbbbbbbbbbb" # Replace with the Object ID of the App Registration

##########################################################

# Create a self-signed cert

$cert = New-SelfSignedCertificate -certstorelocation cert:\currentuser\my -DnsName $fqdn
$pwdSecure = ConvertTo-SecureString -String $pwd -Force -AsPlainText
$path = 'cert:\currentuser\my\' + $cert.Thumbprint
$location="C:\\temp" # path to folder where both the pfx and cer file will be written to
$cerFile = $location + "\\" + $fqdn + ".cer"
$pfxFile = $location + "\\" + $fqdn + ".pfx"
 
# Export the public and private keys
Export-PfxCertificate -cert $path -FilePath $pfxFile -Password $pwdSecure
Export-Certificate -cert $path -FilePath $cerFile

$pfxpath = $pfxFile # path to pfx file
$cerpath = $cerFile # path to cer file
$password = $pwd  # password for the pfx file
 
# Check PowerShell version (minimum 5.1) (.Net) or PowerShell Core (.Net Core) and read the certificate file accordingly
 
if ($PSVersionTable.PSVersion.Major -gt 5)
    { 
        $core = $true
    }
else
    { 
        $core = $false
    }
 
    #  this is for PowerShell Core
    $Secure_String_Pwd = ConvertTo-SecureString $password -AsPlainText -Force
 
    # reading certificate files and creating Certificate Object
    if ($core)
    {
        $pfx_cert = get-content $pfxpath -AsByteStream -Raw
        $cer_cert = get-content $cerpath -AsByteStream -Raw
        $cert = Get-PfxCertificate -FilePath $pfxpath -Password $Secure_String_Pwd
    }
    else
    {
        $pfx_cert = get-content $pfxpath -Encoding Byte
        $cer_cert = get-content $cerpath -Encoding Byte
        # calling Get-PfxCertificate in PowerShell 5.1 prompts for password - using alternative method
        $cert = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new($pfxpath, $password)
    }

 
    # base 64 encode the private key and public key
    $base64pfx = [System.Convert]::ToBase64String($pfx_cert)
    $base64cer = [System.Convert]::ToBase64String($cer_cert)
 
    # getting id for the keyCredential object
    $guid1 = New-Guid
    $guid2 = New-Guid
 
    # get the custom key identifier from the certificate thumbprint:
    $hasher = [System.Security.Cryptography.HashAlgorithm]::Create('sha256')
    $hash = $hasher.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($cert.Thumbprint))
    $customKeyIdentifier = [System.Convert]::ToBase64String($hash)
 
    # get end date and start date for our keycredentials
    $endDateTime = ($cert.NotAfter).ToUniversalTime().ToString( "yyyy-MM-ddTHH:mm:ssZ" )
    $startDateTime = ($cert.NotBefore).ToUniversalTime().ToString( "yyyy-MM-ddTHH:mm:ssZ" )
 
    # building our json payload
    $object = [ordered]@{    
    keyCredentials = @(       
         [ordered]@{            
            customKeyIdentifier = $customKeyIdentifier
            endDateTime = $endDateTime
            keyId = $guid1
            startDateTime = $startDateTime 
            type = "AsymmetricX509Cert"
            usage = "Sign"
            key = $base64pfx
            displayName = "CN=$fqdn" 
        },
        [ordered]@{            
            customKeyIdentifier = $customKeyIdentifier
            endDateTime = $endDateTime
            keyId = $guid2
            startDateTime = $startDateTime 
            type = "AsymmetricX509Cert"
            usage = "Verify"
            key = $base64cer
            displayName = "CN=$fqdn"   
        }
        )  
    passwordCredentials = @(
        [ordered]@{
            customKeyIdentifier = $customKeyIdentifier
            displayName = "CN=$fqdn"
            keyId = $guid1           
            endDateTime = $endDateTime
            startDateTime = $startDateTime
            secretText = $password
            hint = $null
        }
    )
    }
 
Connect-MgGraph -tenantId $tenantId -Scopes Application.ReadWrite.All
$graphuri = "https://graph.microsoft.com/v1.0/applications/$appObjId"
Invoke-MgGraphRequest -Method PATCH -Uri $graphuri -Body $object

    $json = $object | ConvertTo-Json -Depth 99
    Write-Host "JSON Payload:"
    Write-Output $json

驗證令牌簽署金鑰

已啟用宣告對應的應用程式必須附加appid={client_id}至其OpenID Connect元數據要求,以驗證其令牌簽署密鑰。 下列範例顯示您應該使用的 OpenID Connect 元資料檔案格式:

https://login.microsoftonline.com/{tenant}/v2.0/.well-known/openid-configuration?appid={client-id}

更新應用程式指令清單

對於單一租使用者應用程式,您可以在應用程式指令清單中將 屬性設定acceptMappedClaimstrue 如資源類型所述apiApplication。 設定 屬性可讓應用程式使用宣告對應,而不需指定自定義簽署密鑰。

警告

請勿將 multi-tenant 應用程式的 acceptMappedClaims 屬性設定為 true,這可讓惡意執行者為您的應用程式建立宣告對應原則。

要求令牌物件必須使用您Microsoft Entra 租使用者的已驗證功能變數名稱,這表示您應該將 Application ID URI (以 identifierUris 應用程式指令清單中的 表示) 設定為 https://contoso.com/my-api 或 (只要使用預設租使用者名稱) https://contoso.onmicrosoft.com/my-api

如果您未使用已驗證的網域,Microsoft Entra ID 傳 AADSTS501461 回錯誤碼訊息:「_AcceptMappedClaims僅支援符合應用程式 GUID 或租使用者已驗證網域內物件之令牌物件。 請變更資源識別碼,或使用應用程式特定的簽署金鑰。」

進階宣告選項

設定 OIDC 應用程式的進階宣告選項,以公開與 SAML 令牌相同的宣告。 此外,針對想要針對 SAML2.0 和 OIDC 回應令牌使用相同的宣告的應用程式。

核取 [管理宣告] 刀鋒視窗中 [進階宣告選項] 底下的方塊,以設定進階宣告選項