使用 Azure Active Directory B2C 自定義原則收集及操作用戶輸入
Azure Active Directory B2C (Azure AD B2C) 自定義原則可讓您收集使用者輸入。 接著,您可以使用內建方法來操作用戶輸入。
在本文中,您將瞭解如何撰寫自定義原則,以透過圖形使用者介面收集用戶輸入。 接著,您將存取輸入、處理,最後以 JWT 令牌中的宣告的形式傳回這些輸入。 若要完成這項工作,您將:
宣告宣告。 宣告會在 Azure AD B2C 原則執行期間提供數據的暫存記憶體。 它可以儲存使用者的相關信息,例如名字、姓氏或任何其他從使用者或其他系統取得的宣告。 您可以在 Azure AD B2C 自定義原則概觀中深入瞭解宣告。
定義技術配置檔。 技術配置檔提供與不同類型的合作對象通訊的介面。 例如,它可讓您與用戶互動以收集數據。
設定宣告轉換,您用來操作宣告的宣告。
設定內容定義。 內容定義會定義要載入的使用者介面。 稍後您可以 藉由提供自己的自定義 HTML 內容來自定義使用者介面 。
使用自我判斷技術配置檔和 DisplayClaims,設定及顯示使用者介面。
使用協調流程步驟,在指定的序列中呼叫技術配置檔。
必要條件
如果您還沒有 Azure AD B2C 租使用者, 請建立連結至 Azure 訂用帳戶的 Azure AD B2C 租 使用者。
註冊 Web 應用程式,並 啟用標識碼令牌隱含授與。 針對 [重新導向 URI],請使用 https://jwt.ms。
您的計算機中必須安裝 Visual Studio Code (VS Code)。
完成撰寫您的第一個 Azure AD B2C 自定義原則 - Hello World!中的步驟。 本文是建立及執行您自己的自定義原則操作指南系列的一部分。
注意
本文是 Azure Active Directory B2C 操作指南系列 中建立和執行您自己的自訂原則的一部分 。 建議您從第一篇文章開始此系列。
步驟 1 - 宣告宣告
在 objectId 和 訊息 旁邊 宣告其他宣告:
在 VS Code 中,開啟
ContosoCustomPolicy.XML
檔案。在 區
ClaimsSchema
段中,新增下列 ClaimType 宣告:<ClaimType Id="givenName"> <DisplayName>Given Name</DisplayName> <DataType>string</DataType> <UserHelpText>Your given name (also known as first name).</UserHelpText> <UserInputType>TextBox</UserInputType> </ClaimType> <ClaimType Id="surname"> <DisplayName>Surname</DisplayName> <DataType>string</DataType> <UserHelpText>Your surname (also known as family name or last name).</UserHelpText> <UserInputType>TextBox</UserInputType> </ClaimType> <ClaimType Id="displayName"> <DisplayName>Display Name</DisplayName> <DataType>string</DataType> <UserHelpText>Your display name.</UserHelpText> <UserInputType>TextBox</UserInputType> </ClaimType>
我們已宣告三個宣告類型: givenName 、 surname 和 displayName 。 這些宣告包括 DataType
、 UserInputType
和 DisplayName
元素:
- DataType 指定宣告保留之值的資料類型。 深入瞭解 DataType 元素支援的 資料類型 。
- UserInputType 指定要從使用者收集宣告值時,出現在使用者介面上的 UI 控制項。 深入瞭解 Azure AD B2C 支援 的使用者 輸入類型。
- DisplayName 指定 UI 控制項的標籤,如果您想要從使用者收集宣告的值,該控制項會出現在使用者介面上。
步驟 2 - 定義宣告轉換
ClaimsTransformation 包含用來將指定宣告轉換成另一個宣告的函式。 例如,您可以將字串宣告從小寫變更為大寫。 深入瞭解 Azure AD B2C 支援的宣告轉換。
在 檔案中
ContosoCustomPolicy.XML
,將 專案新增<ClaimsTransformations>
為 區段的BuildingBlocks
子系。<ClaimsTransformations> </ClaimsTransformations>
在 元素內
ClaimsTransformations
新增下列程式碼:<ClaimsTransformation Id="GenerateRandomObjectIdTransformation" TransformationMethod="CreateRandomString"> <InputParameters> <InputParameter Id="randomGeneratorType" DataType="string" Value="GUID"/> </InputParameters> <OutputClaims> <OutputClaim ClaimTypeReferenceId="objectId" TransformationClaimType="outputClaim"/> </OutputClaims> </ClaimsTransformation> <ClaimsTransformation Id="CreateDisplayNameTransformation" TransformationMethod="FormatStringMultipleClaims"> <InputClaims> <InputClaim ClaimTypeReferenceId="givenName" TransformationClaimType="inputClaim1"/> <InputClaim ClaimTypeReferenceId="surname" TransformationClaimType="inputClaim2"/> </InputClaims> <InputParameters> <InputParameter Id="stringFormat" DataType="string" Value="{0} {1}"/> </InputParameters> <OutputClaims> <OutputClaim ClaimTypeReferenceId="displayName" TransformationClaimType="outputClaim"/> </OutputClaims> </ClaimsTransformation> <ClaimsTransformation Id="CreateMessageTransformation" TransformationMethod="FormatStringClaim"> <InputClaims> <InputClaim ClaimTypeReferenceId="displayName" TransformationClaimType="inputClaim"/> </InputClaims> <InputParameters> <InputParameter Id="stringFormat" DataType="string" Value="Hello {0}"/> </InputParameters> <OutputClaims> <OutputClaim ClaimTypeReferenceId="message" TransformationClaimType="outputClaim"/> </OutputClaims> </ClaimsTransformation>
我們已設定三個宣告轉換:
GenerateRandomObjectIdTransformation 會產生由 CreateRandomString 方法指定的 隨機字串。 objectId 宣告會以 專案指定的
OutputClaim
產生的字串進行更新。CreateDisplayNameTransformation 會串連 givenName 和 surname ,以形成 displayName 。
CreateMessageTransformation 會串連 Hello 和 displayName 以形成 訊息 。
步驟 3 - 設定內容定義
ContentDefinitions 可讓您指定 HTML 範本的 URL,以控制您向使用者顯示之網頁的配置。 您可以為每個步驟指定特定的使用者介面,例如登入或註冊、密碼重設或錯誤頁面。
若要新增內容定義,請在 BuildingBlocks
檔案的 ContosoCustomPolicy.XML
區段中新增下列程式碼:
<ContentDefinitions>
<ContentDefinition Id="SelfAssertedContentDefinition">
<LoadUri>~/tenant/templates/AzureBlue/selfAsserted.cshtml</LoadUri>
<RecoveryUri>~/common/default_page_error.html</RecoveryUri>
<DataUri>urn:com:microsoft:aad:b2c:elements:contract:selfasserted:2.1.7</DataUri>
</ContentDefinition>
</ContentDefinitions>
步驟 4 - 設定技術設定檔
在自訂原則中, TechnicalProfile 是實作功能的專案。 既然您已定義宣告和宣告轉換,您需要技術設定檔來執行您的定義。 技術設定檔會在 專案內 ClaimsProvider
宣告。
Azure AD B2C 提供一組技術設定檔。 每個技術設定檔都會執行特定角色。 例如,您可以使用 REST 技術設定檔 對服務端點進行 HTTP 呼叫。 您可以使用宣告轉換技術設定檔來執行您在宣告轉換中定義的作業。 深入瞭解 Azure AD B2C 自訂原則所提供的技術設定檔 類型。
設定宣告的值
若要設定 objectId、displayName 和 訊息 宣告的值 ,您可以設定執行 GenerateRandomObjectIdTransformation、 CreateDisplayNameTransformation 和 CreateMessageTransformation 宣告轉換的技術設定檔 。 宣告轉換是由 元素中 OutputClaimsTransformations
定義的順序來執行。 例如,它會先建立顯示名稱,然後建立訊息。
將下列
ClaimsProvider
內容新增為 區段的ClaimsProviders
子系。<ClaimsProvider> <DisplayName>Technical Profiles to generate claims</DisplayName> </ClaimsProvider>
若要設定 objectId 、 displayName 和 訊息 宣告的值 ,請在您剛才建立的專案
ClaimsProvider
內新增下列程式碼:<!--<ClaimsProvider>--> <TechnicalProfiles> <TechnicalProfile Id="ClaimGenerator"> <DisplayName>Generate Object ID, displayName and message Claims Technical Profile.</DisplayName> <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.ClaimsTransformationProtocolProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/> <OutputClaims> <OutputClaim ClaimTypeReferenceId="objectId"/> <OutputClaim ClaimTypeReferenceId="displayName"/> <OutputClaim ClaimTypeReferenceId="message"/> </OutputClaims> <OutputClaimsTransformations> <OutputClaimsTransformation ReferenceId="GenerateRandomObjectIdTransformation"/> <OutputClaimsTransformation ReferenceId="CreateDisplayNameTransformation"/> <OutputClaimsTransformation ReferenceId="CreateMessageTransformation"/> </OutputClaimsTransformations> </TechnicalProfile> </TechnicalProfiles> <!--</ClaimsProvider>-->
收集使用者輸入
您可以從 givenName 和 surname 產生 displayName 宣告 ,因此您必須收集然後作為使用者輸入。 若要收集使用者輸入,您可以使用稱為 Self-Asserted 的技術配置檔案類型。 當您設定自我判斷技術設定檔時,您必須將內容定義參考為自我判斷技術設定檔,以負責顯示使用者介面。
將下列
ClaimsProvider
內容新增為 區段的ClaimsProviders
子系。<ClaimsProvider> <DisplayName>Technical Profiles to collect user's details </DisplayName> </ClaimsProvider>
在您剛才建立的
ClaimsProvider
元素內新增下列程式碼:<TechnicalProfiles> <TechnicalProfile Id="UserInformationCollector"> <DisplayName>Collect User Input Technical Profile</DisplayName> <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.SelfAssertedAttributeProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/> <Metadata> <Item Key="ContentDefinitionReferenceId">SelfAssertedContentDefinition</Item> </Metadata> <DisplayClaims> <DisplayClaim ClaimTypeReferenceId="givenName" Required="true"/> <DisplayClaim ClaimTypeReferenceId="surname" Required="true"/> </DisplayClaims> <OutputClaims> <OutputClaim ClaimTypeReferenceId="givenName"/> <OutputClaim ClaimTypeReferenceId="surname"/> </OutputClaims> </TechnicalProfile> </TechnicalProfiles>
請注意 givenName 和 surname 宣告的 兩個顯示 宣告。 這兩個宣告都會標示為必要,因此使用者必須先輸入值,才能提交顯示給他們的表單。 宣告會以 DisplayClaims 元素中所 定義的順序在螢幕上顯示, 例如指定名稱 ,然後 顯示 Surname 。
步驟 5 - 定義使用者旅程圖
您可以使用使用者旅程圖來定義呼叫技術設定檔的順序。 您可以使用 OrchestrationSteps
元素來指定使用者旅程圖中的步驟。
以下列程式碼取代 User Journey 的現有內容 HelloWorldJourney
:
<OrchestrationSteps>
<OrchestrationStep Order="1" Type="ClaimsExchange">
<ClaimsExchanges>
<ClaimsExchange Id="GetUserInformationClaimsExchange" TechnicalProfileReferenceId="UserInformationCollector"/>
</ClaimsExchanges>
</OrchestrationStep>
<OrchestrationStep Order="2" Type="ClaimsExchange">
<ClaimsExchanges>
<ClaimsExchange Id="GetMessageClaimsExchange" TechnicalProfileReferenceId="ClaimGenerator"/>
</ClaimsExchanges>
</OrchestrationStep>
<OrchestrationStep Order="3" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="JwtIssuer"/>
</OrchestrationSteps>
根據協調流程步驟,我們會收集使用者輸入、設定 objectId 、 displayName 和 訊息 宣告的值 ,最後傳送 Jwt 權杖。
步驟 6 - 更新信賴憑證者
以下列程式碼取代 區段的 RelyingParty
元素內容 OutputClaims
:
<OutputClaim ClaimTypeReferenceId="objectId" PartnerClaimType="sub"/>
<OutputClaim ClaimTypeReferenceId="displayName"/>
<OutputClaim ClaimTypeReferenceId="message"/>
完成 步驟 6 之後, ContosoCustomPolicy.XML
檔案看起來應該類似下列程式碼:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<TrustFrameworkPolicy xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://schemas.microsoft.com/online/cpim/schemas/2013/06"
PolicySchemaVersion="0.3.0.0" TenantId="yourtenant.onmicrosoft.com"
PolicyId="B2C_1A_ContosoCustomPolicy"
PublicPolicyUri="http://yourtenant.onmicrosoft.com/B2C_1A_ContosoCustomPolicy">
<BuildingBlocks>
<ClaimsSchema>
<ClaimType Id="objectId">
<DisplayName>unique object Id for subject of the claims being returned</DisplayName>
<DataType>string</DataType>
</ClaimType>
<ClaimType Id="message">
<DisplayName>Will hold Hello World message</DisplayName>
<DataType>string</DataType>
</ClaimType>
<ClaimType Id="givenName">
<DisplayName>Given Name</DisplayName>
<DataType>string</DataType>
<UserHelpText>Your given name (also known as first name).</UserHelpText>
<UserInputType>TextBox</UserInputType>
</ClaimType>
<ClaimType Id="surname">
<DisplayName>Surname</DisplayName>
<DataType>string</DataType>
<UserHelpText>Your surname (also known as family name or last name).</UserHelpText>
<UserInputType>TextBox</UserInputType>
</ClaimType>
<ClaimType Id="displayName">
<DisplayName>Display Name</DisplayName>
<DataType>string</DataType>
<UserHelpText>Your display name.</UserHelpText>
<UserInputType>TextBox</UserInputType>
</ClaimType>
</ClaimsSchema>
<ClaimsTransformations>
<ClaimsTransformation Id="GenerateRandomObjectIdTransformation" TransformationMethod="CreateRandomString">
<InputParameters>
<InputParameter Id="randomGeneratorType" DataType="string" Value="GUID"/>
</InputParameters>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="objectId" TransformationClaimType="outputClaim"/>
</OutputClaims>
</ClaimsTransformation>
<ClaimsTransformation Id="CreateDisplayNameTransformation" TransformationMethod="FormatStringMultipleClaims">
<InputClaims>
<InputClaim ClaimTypeReferenceId="givenName" TransformationClaimType="inputClaim1"/>
<InputClaim ClaimTypeReferenceId="surname" TransformationClaimType="inputClaim2"/>
</InputClaims>
<InputParameters>
<InputParameter Id="stringFormat" DataType="string" Value="{0} {1}"/>
</InputParameters>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="displayName" TransformationClaimType="outputClaim"/>
</OutputClaims>
</ClaimsTransformation>
<ClaimsTransformation Id="CreateMessageTransformation" TransformationMethod="FormatStringClaim">
<InputClaims>
<InputClaim ClaimTypeReferenceId="displayName" TransformationClaimType="inputClaim"/>
</InputClaims>
<InputParameters>
<InputParameter Id="stringFormat" DataType="string" Value="Hello {0}"/>
</InputParameters>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="message" TransformationClaimType="outputClaim"/>
</OutputClaims>
</ClaimsTransformation>
</ClaimsTransformations>
<ContentDefinitions>
<ContentDefinition Id="SelfAssertedContentDefinition">
<LoadUri>~/tenant/templates/AzureBlue/selfAsserted.cshtml</LoadUri>
<RecoveryUri>~/common/default_page_error.html</RecoveryUri>
<DataUri>urn:com:microsoft:aad:b2c:elements:contract:selfasserted:2.1.7</DataUri>
</ContentDefinition>
</ContentDefinitions>
</BuildingBlocks>
<!--Claims Providers Here-->
<ClaimsProviders>
<ClaimsProvider>
<DisplayName>Token Issuer</DisplayName>
<TechnicalProfiles>
<TechnicalProfile Id="JwtIssuer">
<DisplayName>JWT Issuer</DisplayName>
<Protocol Name="None"/>
<OutputTokenFormat>JWT</OutputTokenFormat>
<Metadata>
<Item Key="client_id">{service:te}</Item>
<Item Key="issuer_refresh_token_user_identity_claim_type">objectId</Item>
<Item Key="SendTokenResponseBodyWithJsonNumbers">true</Item>
</Metadata>
<CryptographicKeys>
<Key Id="issuer_secret" StorageReferenceId="B2C_1A_TokenSigningKeyContainer"/>
<Key Id="issuer_refresh_token_key" StorageReferenceId="B2C_1A_TokenEncryptionKeyContainer"/>
</CryptographicKeys>
</TechnicalProfile>
</TechnicalProfiles>
</ClaimsProvider>
<ClaimsProvider>
<DisplayName>Trustframework Policy Engine TechnicalProfiles</DisplayName>
<TechnicalProfiles>
<TechnicalProfile Id="TpEngine_c3bd4fe2-1775-4013-b91d-35f16d377d13">
<DisplayName>Trustframework Policy Engine Default Technical Profile</DisplayName>
<Protocol Name="None"/>
<Metadata>
<Item Key="url">{service:te}</Item>
</Metadata>
</TechnicalProfile>
</TechnicalProfiles>
</ClaimsProvider>
<ClaimsProvider>
<DisplayName>Claim Generator Technical Profiles</DisplayName>
<TechnicalProfiles>
<TechnicalProfile Id="ClaimGenerator">
<DisplayName>Generate Object ID, displayName and message Claims Technical Profile.</DisplayName>
<Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.ClaimsTransformationProtocolProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="objectId"/>
<OutputClaim ClaimTypeReferenceId="displayName"/>
<OutputClaim ClaimTypeReferenceId="message"/>
</OutputClaims>
<OutputClaimsTransformations>
<OutputClaimsTransformation ReferenceId="GenerateRandomObjectIdTransformation"/>
<OutputClaimsTransformation ReferenceId="CreateDisplayNameTransformation"/>
<OutputClaimsTransformation ReferenceId="CreateMessageTransformation"/>
</OutputClaimsTransformations>
</TechnicalProfile>
</TechnicalProfiles>
</ClaimsProvider>
<ClaimsProvider>
<DisplayName>Technical Profiles to collect user's details</DisplayName>
<TechnicalProfiles>
<TechnicalProfile Id="UserInformationCollector">
<DisplayName>Collect User Input Technical Profile</DisplayName>
<Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.SelfAssertedAttributeProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
<Metadata>
<Item Key="ContentDefinitionReferenceId">SelfAssertedContentDefinition</Item>
</Metadata>
<DisplayClaims>
<DisplayClaim ClaimTypeReferenceId="givenName" Required="true"/>
<DisplayClaim ClaimTypeReferenceId="surname" Required="true"/>
</DisplayClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="givenName"/>
<OutputClaim ClaimTypeReferenceId="surname"/>
</OutputClaims>
</TechnicalProfile>
</TechnicalProfiles>
</ClaimsProvider>
</ClaimsProviders>
<UserJourneys>
<UserJourney Id="HelloWorldJourney">
<OrchestrationSteps>
<OrchestrationStep Order="1" Type="ClaimsExchange">
<ClaimsExchanges>
<ClaimsExchange Id="GetUserInformationClaimsExchange" TechnicalProfileReferenceId="UserInformationCollector"/>
</ClaimsExchanges>
</OrchestrationStep>
<OrchestrationStep Order="2" Type="ClaimsExchange">
<ClaimsExchanges>
<ClaimsExchange Id="GetMessageClaimsExchange" TechnicalProfileReferenceId="ClaimGenerator"/>
</ClaimsExchanges>
</OrchestrationStep>
<OrchestrationStep Order="3" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="JwtIssuer"/>
</OrchestrationSteps>
</UserJourney>
</UserJourneys>
<RelyingParty><!--
Relying Party Here that's your policy’s entry point
Specify the User Journey to execute
Specify the claims to include in the token that is returned when the policy runs
-->
<DefaultUserJourney ReferenceId="HelloWorldJourney"/>
<TechnicalProfile Id="HelloWorldPolicyProfile">
<DisplayName>Hello World Policy Profile</DisplayName>
<Protocol Name="OpenIdConnect"/>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="objectId" PartnerClaimType="sub"/>
<OutputClaim ClaimTypeReferenceId="displayName"/>
<OutputClaim ClaimTypeReferenceId="message"/>
</OutputClaims>
<SubjectNamingInfo ClaimType="sub"/>
</TechnicalProfile>
</RelyingParty>
</TrustFrameworkPolicy>
如果您尚未這麼做,請將 取代 yourtenant
為租使用者名稱的子域部分,例如 contoso
。 瞭解如何 取得您的租使用者名稱 。
步驟 3 - 上傳自訂原則檔案
請遵循上傳自訂原則檔案 中的 步驟。 如果您要上傳與入口網站中已有相同名稱的檔案,請確定您已選取 [覆寫自訂原則] ,如果檔案已經存在 。
步驟 4 - 測試自訂原則
在 [自訂原則] 底下 ,選取 [B2C_1A_CONTOSOCUSTOMPOLICY]。
針對在 自訂原則的概觀頁面上選取應用程式 ,請選取您先前註冊的 Web 應用程式,例如 webapp1 。 請確定 [選取回復 URL ] 值已設定為
https://jwt.ms
。選取 [ 立即 執行] 按鈕。
輸入 [指定名稱 ] 和 [姓氏 ],然後選取 [ 繼續 ]。
原則完成執行之後,系統會將您重新導向至 https://jwt.ms
,您會看到已解碼的 JWT 權杖。 看起來類似下列 JWT 權杖程式碼片段:
{
"typ": "JWT",
"alg": "RS256",
"kid": "pxLOMWFg...."
}.{
...
"sub": "c7ae4515-f7a7....",
...
"acr": "b2c_1a_contosocustompolicy",
...
"name": "Maurice Paulet",
"message": "Hello Maurice Paulet"
}.[Signature]
下一步
接下來,瞭解:
關於 Azure AD B2C 自訂原則中的技術設定檔 類型。
如何使用 自訂原則 驗證使用者輸入。