如何使用自定义策略检查用户是否存在于 AD B2C 中?
How to check user exists in AD B2C, using custom policy?
我有一个注册流程,它工作正常并且是多步骤的:
- 联系方式
- 验证
- 密码
现在的流程是,在完成所有步骤后,将创建一个新用户,如果该用户名已经存在,那么在最后一步我会收到一条错误消息,指出该用户已经存在。现在我需要改变这个流程。输入联系方式(电子邮件)后,我想检查该用户是否存在。如果它存在,那么我需要在第一步本身的最后一步中显示错误消息,并阻止移动到下一步的旅程。
为了实现这一点,我所做的是:
创建了一个使用电子邮件读取用户详细信息的 TP,并将其作为第一步的验证技术配置文件:
<TechnicalProfile Id="AAD-CheckUserExist">
<Metadata>
<Item Key="Operation">Read</Item>
<Item Key="RaiseErrorIfClaimsPrincipalAlreadyExists">true</Item>
</Metadata>
<IncludeInSso>false</IncludeInSso>
<InputClaims>
<InputClaim ClaimTypeReferenceId="email" PartnerClaimType="signInNames.emailAddress" />
</InputClaims>
<OutputClaims>
<!-- Required claims -->
<OutputClaim ClaimTypeReferenceId="objectId" />
<OutputClaim ClaimTypeReferenceId="authenticationSource" DefaultValue="localAccountAuthentication" />
<!-- Optional claims -->
<OutputClaim ClaimTypeReferenceId="userPrincipalName" />
<OutputClaim ClaimTypeReferenceId="displayName" />
<OutputClaim ClaimTypeReferenceId="accountEnabled" />
<OutputClaim ClaimTypeReferenceId="otherMails" />
<OutputClaim ClaimTypeReferenceId="signInNames.emailAddress"/>
<OutputClaim ClaimTypeReferenceId="signInNames.phoneNumber"/>
<OutputClaim ClaimTypeReferenceId="givenName" />
<OutputClaim ClaimTypeReferenceId="surname" />
</OutputClaims>
<IncludeTechnicalProfile ReferenceId="AAD-Common" />
</TechnicalProfile>
并将<Item Key="RaiseErrorIfClaimsPrincipalAlreadyExists">true</Item>
添加到<Metadata>
.
以下是验证配置文件部分:
<ValidationTechnicalProfiles>
<ValidationTechnicalProfile ReferenceId="AAD-CheckUserExist" ContinueOnError="false"/>
</ValidationTechnicalProfiles>
但它没有按预期工作,我在点击第一步的下一步后尝试与现有用户一起移动验证步骤,没有任何错误。
RaiseErrorIfClaimsPrincipalAlreadyExists 仅在操作为 Write.
时有效
读取操作后,仅当用户已存在时才会填充 objectId 声明。您必须 Read 和 RaiseErrorIfClaimsPrincipalDoesNotExist = false 然后您可以使用 ClaimTransformations 和 ValidationTechnicalProfiles 来阻止 UserJourney if objectId != null
编辑:
例子
我在 AAD 声明提供程序下创建了一个 AAD-UserReadUsingEmailAddress-RaiseIfExists 技术配置文件
<TechnicalProfile Id="AAD-UserReadUsingEmailAddress-RaiseIfExists">
<Metadata>
<Item Key="Operation">Read</Item>
<Item Key="RaiseErrorIfClaimsPrincipalDoesNotExist">false</Item>
</Metadata>
<IncludeInSso>false</IncludeInSso>
<InputClaims>
<InputClaim ClaimTypeReferenceId="email" PartnerClaimType="signInNames.emailAddress" Required="true" />
</InputClaims>
<OutputClaims>
<!-- Required claims -->
<OutputClaim ClaimTypeReferenceId="objectId" DefaultValue="NOTFOUND" />
<OutputClaim ClaimTypeReferenceId="objectIdNotFound" DefaultValue="NOTFOUND" AlwaysUseDefaultValue="true" />
</OutputClaims>
<OutputClaimsTransformations>
<OutputClaimsTransformation ReferenceId="AssertObjectIdObjectIdNotFoundAreEqual" />
</OutputClaimsTransformations>
<IncludeTechnicalProfile ReferenceId="AAD-Common" />
</TechnicalProfile>
如您所见,我正在使用电子邮件声明来搜索用户并仅返回 objectId。请注意 RaiseErrorIfClaimsPrincipalDoesNotExist = false 以及 objectId 的默认值为 NOTFOUND。根据 AlwaysUseDefaultValue="true"
,objectIdNotFound 将始终为 NOTFOUND
objectIdNotFound 是一个简单的字符串声明
<ClaimType Id="objectIdNotFound">
<DisplayName>Used for comparison</DisplayName>
<DataType>string</DataType>
</ClaimType>
AssertObjectIdObjectIdNotFoundAreEqual OutputClaim 转换如下:
<ClaimsTransformation Id="AssertObjectIdObjectIdNotFoundAreEqual" TransformationMethod="AssertStringClaimsAreEqual">
<InputClaims>
<InputClaim ClaimTypeReferenceId="objectId" TransformationClaimType="inputClaim1" />
<InputClaim ClaimTypeReferenceId="objectIdNotFound" TransformationClaimType="inputClaim2" />
</InputClaims>
<InputParameters>
<InputParameter Id="stringComparison" DataType="string" Value="ordinalIgnoreCase" />
</InputParameters>
</ClaimsTransformation>
然后我在我的 SelfAsserted TechnicalProfile
中使用 AAD-UserReadUsingEmailAddress-RaiseIfExists 作为验证 TechnicalProfile
<TechnicalProfile Id="LocalAccountSignUpWithLogonEmail-CheckEmailAlreadyExists">
<DisplayName>Email signup</DisplayName>
<Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.SelfAssertedAttributeProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<Metadata>
<Item Key="IpAddressClaimReferenceId">IpAddress</Item>
<Item Key="ContentDefinitionReferenceId">api.localaccountsignup</Item>
<Item Key="language.button_continue">Next</Item>
<Item Key="UserMessageIfClaimsTransformationStringsAreNotEqual">There is another user with this email address</Item>
</Metadata>
<InputClaims>
<InputClaim ClaimTypeReferenceId="email" />
</InputClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="email" PartnerClaimType="Verified.Email" Required="true" />
</OutputClaims>
<ValidationTechnicalProfiles>
<ValidationTechnicalProfile ReferenceId="AAD-UserReadUsingEmailAddress-RaiseIfExists" />
</ValidationTechnicalProfiles>
</TechnicalProfile>
使用此设置,当您单击 "Continue" 时,将执行验证技术配置文件,如果已经有用户使用插入的电子邮件,则会引发错误。发生这种情况是因为如果找到用户,objectId 将是一个 guid,它不会等于 "NOTFOUND"。
您可以通过 UserMessageIfClaimsTransformationStringsAreNotEqual 元数据更改错误消息。
HTH, F.
我有一个注册流程,它工作正常并且是多步骤的:
- 联系方式
- 验证
- 密码
现在的流程是,在完成所有步骤后,将创建一个新用户,如果该用户名已经存在,那么在最后一步我会收到一条错误消息,指出该用户已经存在。现在我需要改变这个流程。输入联系方式(电子邮件)后,我想检查该用户是否存在。如果它存在,那么我需要在第一步本身的最后一步中显示错误消息,并阻止移动到下一步的旅程。
为了实现这一点,我所做的是:
创建了一个使用电子邮件读取用户详细信息的 TP,并将其作为第一步的验证技术配置文件:
<TechnicalProfile Id="AAD-CheckUserExist">
<Metadata>
<Item Key="Operation">Read</Item>
<Item Key="RaiseErrorIfClaimsPrincipalAlreadyExists">true</Item>
</Metadata>
<IncludeInSso>false</IncludeInSso>
<InputClaims>
<InputClaim ClaimTypeReferenceId="email" PartnerClaimType="signInNames.emailAddress" />
</InputClaims>
<OutputClaims>
<!-- Required claims -->
<OutputClaim ClaimTypeReferenceId="objectId" />
<OutputClaim ClaimTypeReferenceId="authenticationSource" DefaultValue="localAccountAuthentication" />
<!-- Optional claims -->
<OutputClaim ClaimTypeReferenceId="userPrincipalName" />
<OutputClaim ClaimTypeReferenceId="displayName" />
<OutputClaim ClaimTypeReferenceId="accountEnabled" />
<OutputClaim ClaimTypeReferenceId="otherMails" />
<OutputClaim ClaimTypeReferenceId="signInNames.emailAddress"/>
<OutputClaim ClaimTypeReferenceId="signInNames.phoneNumber"/>
<OutputClaim ClaimTypeReferenceId="givenName" />
<OutputClaim ClaimTypeReferenceId="surname" />
</OutputClaims>
<IncludeTechnicalProfile ReferenceId="AAD-Common" />
</TechnicalProfile>
并将<Item Key="RaiseErrorIfClaimsPrincipalAlreadyExists">true</Item>
添加到<Metadata>
.
以下是验证配置文件部分:
<ValidationTechnicalProfiles>
<ValidationTechnicalProfile ReferenceId="AAD-CheckUserExist" ContinueOnError="false"/>
</ValidationTechnicalProfiles>
但它没有按预期工作,我在点击第一步的下一步后尝试与现有用户一起移动验证步骤,没有任何错误。
RaiseErrorIfClaimsPrincipalAlreadyExists 仅在操作为 Write.
时有效读取操作后,仅当用户已存在时才会填充 objectId 声明。您必须 Read 和 RaiseErrorIfClaimsPrincipalDoesNotExist = false 然后您可以使用 ClaimTransformations 和 ValidationTechnicalProfiles 来阻止 UserJourney if objectId != null
编辑: 例子
我在 AAD 声明提供程序下创建了一个 AAD-UserReadUsingEmailAddress-RaiseIfExists 技术配置文件
<TechnicalProfile Id="AAD-UserReadUsingEmailAddress-RaiseIfExists">
<Metadata>
<Item Key="Operation">Read</Item>
<Item Key="RaiseErrorIfClaimsPrincipalDoesNotExist">false</Item>
</Metadata>
<IncludeInSso>false</IncludeInSso>
<InputClaims>
<InputClaim ClaimTypeReferenceId="email" PartnerClaimType="signInNames.emailAddress" Required="true" />
</InputClaims>
<OutputClaims>
<!-- Required claims -->
<OutputClaim ClaimTypeReferenceId="objectId" DefaultValue="NOTFOUND" />
<OutputClaim ClaimTypeReferenceId="objectIdNotFound" DefaultValue="NOTFOUND" AlwaysUseDefaultValue="true" />
</OutputClaims>
<OutputClaimsTransformations>
<OutputClaimsTransformation ReferenceId="AssertObjectIdObjectIdNotFoundAreEqual" />
</OutputClaimsTransformations>
<IncludeTechnicalProfile ReferenceId="AAD-Common" />
</TechnicalProfile>
如您所见,我正在使用电子邮件声明来搜索用户并仅返回 objectId。请注意 RaiseErrorIfClaimsPrincipalDoesNotExist = false 以及 objectId 的默认值为 NOTFOUND。根据 AlwaysUseDefaultValue="true"
,objectIdNotFound 将始终为 NOTFOUNDobjectIdNotFound 是一个简单的字符串声明
<ClaimType Id="objectIdNotFound">
<DisplayName>Used for comparison</DisplayName>
<DataType>string</DataType>
</ClaimType>
AssertObjectIdObjectIdNotFoundAreEqual OutputClaim 转换如下:
<ClaimsTransformation Id="AssertObjectIdObjectIdNotFoundAreEqual" TransformationMethod="AssertStringClaimsAreEqual">
<InputClaims>
<InputClaim ClaimTypeReferenceId="objectId" TransformationClaimType="inputClaim1" />
<InputClaim ClaimTypeReferenceId="objectIdNotFound" TransformationClaimType="inputClaim2" />
</InputClaims>
<InputParameters>
<InputParameter Id="stringComparison" DataType="string" Value="ordinalIgnoreCase" />
</InputParameters>
</ClaimsTransformation>
然后我在我的 SelfAsserted TechnicalProfile
中使用 AAD-UserReadUsingEmailAddress-RaiseIfExists 作为验证 TechnicalProfile <TechnicalProfile Id="LocalAccountSignUpWithLogonEmail-CheckEmailAlreadyExists">
<DisplayName>Email signup</DisplayName>
<Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.SelfAssertedAttributeProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<Metadata>
<Item Key="IpAddressClaimReferenceId">IpAddress</Item>
<Item Key="ContentDefinitionReferenceId">api.localaccountsignup</Item>
<Item Key="language.button_continue">Next</Item>
<Item Key="UserMessageIfClaimsTransformationStringsAreNotEqual">There is another user with this email address</Item>
</Metadata>
<InputClaims>
<InputClaim ClaimTypeReferenceId="email" />
</InputClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="email" PartnerClaimType="Verified.Email" Required="true" />
</OutputClaims>
<ValidationTechnicalProfiles>
<ValidationTechnicalProfile ReferenceId="AAD-UserReadUsingEmailAddress-RaiseIfExists" />
</ValidationTechnicalProfiles>
</TechnicalProfile>
使用此设置,当您单击 "Continue" 时,将执行验证技术配置文件,如果已经有用户使用插入的电子邮件,则会引发错误。发生这种情况是因为如果找到用户,objectId 将是一个 guid,它不会等于 "NOTFOUND"。 您可以通过 UserMessageIfClaimsTransformationStringsAreNotEqual 元数据更改错误消息。
HTH, F.