我在 IEF 中为本地帐户的注册流程制定了自定义策略。此流程的想法是注册用户并将用户写入 Azure AD B2C。 IEF 策略加载良好,当我运行用户流程时,我得到了预期的视图。除了密码和确认密码之外的所有字段都是只读的,因为它们从 URL 查询中读取数据。
现在说说我遇到的错误。当我提交表单时,出现以下错误
Unable to validate the information provided.
。
我添加了
<ValidationTechnicalProfile ReferenceId="AAD-UserWriteUsingLogonEmail" />
,因为我认为这是<TechnicalProfile Id="SelfAsserted-SignUp">
内部的问题。但仍然是同样的问题。我不知道为什么会发生这种情况。
附注信任框架基础是 Azure AD B2C 入门包(本地帐户)GitHub 中的默认框架:TrustFrameworkBase 代码链接
下面是我的自定义注册策略代码(TrustFrameworkExtensions.xml):
<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="tenantId"
PolicyId="B2C_1A_TrustFrameworkExtensions"
PublicPolicyUri="tenantId/B2C_1A_TrustFrameworkExtensions">
<BasePolicy>
<TenantId>tenantID</TenantId>
<PolicyId>B2C_1A_TrustFrameworkBase</PolicyId>
</BasePolicy>
<BuildingBlocks>
<ClaimsSchema>
<ClaimType Id="email">
<DisplayName>Email Address</DisplayName>
<DataType>string</DataType>
<DefaultPartnerClaimTypes>
<Protocol Name="OAuth2" PartnerClaimType="email" />
</DefaultPartnerClaimTypes>
<UserHelpText>Your email address</UserHelpText>
<UserInputType>Readonly</UserInputType>
</ClaimType>
<ClaimType Id="givenName">
<DisplayName>Given Name</DisplayName>
<DataType>string</DataType>
<DefaultPartnerClaimTypes>
<Protocol Name="OAuth2" PartnerClaimType="given_name" />
</DefaultPartnerClaimTypes>
<UserHelpText>Your given name</UserHelpText>
<UserInputType>Readonly</UserInputType>
</ClaimType>
<ClaimType Id="surname">
<DisplayName>Surname</DisplayName>
<DataType>string</DataType>
<DefaultPartnerClaimTypes>
<Protocol Name="OAuth2" PartnerClaimType="family_name" />
</DefaultPartnerClaimTypes>
<UserHelpText>Your surname</UserHelpText>
<UserInputType>Readonly</UserInputType>
</ClaimType>
<!-- Job Title Claim -->
<ClaimType Id="jobTitle">
<DisplayName>Job Title</DisplayName>
<DataType>string</DataType>
<DefaultPartnerClaimTypes>
<Protocol Name="OAuth2" PartnerClaimType="job_title" />
</DefaultPartnerClaimTypes>
<UserHelpText>Your job title</UserHelpText>
<UserInputType>Readonly</UserInputType>
</ClaimType>
<!-- Mobile Phone Claim -->
<ClaimType Id="mobilePhone">
<DisplayName>Mobile Phone</DisplayName>
<DataType>string</DataType>
<DefaultPartnerClaimTypes>
<Protocol Name="OAuth2" PartnerClaimType="mobile_phone" />
</DefaultPartnerClaimTypes>
<UserHelpText>Your mobile phone number</UserHelpText>
<UserInputType>Readonly</UserInputType>
</ClaimType>
<!-- Organisation Name Claim -->
<ClaimType Id="organisationName">
<DisplayName>Organisation Name</DisplayName>
<DataType>string</DataType>
<DefaultPartnerClaimTypes>
<Protocol Name="OAuth2" PartnerClaimType="organisation_name" />
</DefaultPartnerClaimTypes>
<UserHelpText>Your organisation name</UserHelpText>
<UserInputType>Readonly</UserInputType>
</ClaimType>
<!-- Password Claim -->
<ClaimType Id="password">
<DisplayName>Password</DisplayName>
<DataType>string</DataType>
<UserHelpText>Enter your password</UserHelpText>
<UserInputType>Password</UserInputType>
</ClaimType>
<!-- Confirm Password Claim -->
<ClaimType Id="confirmPassword">
<DisplayName>Confirm Password</DisplayName>
<DataType>string</DataType>
<UserHelpText>Confirm your password</UserHelpText>
<UserInputType>Password</UserInputType>
</ClaimType>
</ClaimsSchema>
</BuildingBlocks>
<ClaimsProviders>
<ClaimsProvider>
<DisplayName>Self Asserted</DisplayName>
<TechnicalProfiles>
<TechnicalProfile Id="SelfAsserted-SignUp">
<DisplayName>User Sign-Up</DisplayName>
<Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.SelfAssertedAttributeProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<Metadata>
<Item Key="ContentDefinitionReferenceId">api.selfasserted</Item>
<Item Key="IncludeClaimResolvingInClaimsHandling">true</Item>
</Metadata>
<InputClaims>
<InputClaim ClaimTypeReferenceId="email" DefaultValue="{OAuth-KV:email}" AlwaysUseDefaultValue="true" />
<InputClaim ClaimTypeReferenceId="givenName" DefaultValue="{OAuth-KV:given_name}" AlwaysUseDefaultValue="true" />
<InputClaim ClaimTypeReferenceId="surname" DefaultValue="{{OAuth-KV:surname}}" AlwaysUseDefaultValue="true" />
<InputClaim ClaimTypeReferenceId="jobTitle" DefaultValue="{OAuth-KV:job_title}" AlwaysUseDefaultValue="true" />
<InputClaim ClaimTypeReferenceId="mobilePhone" DefaultValue="{OAuth-KV:mobile_phone}" AlwaysUseDefaultValue="true" />
<InputClaim ClaimTypeReferenceId="organisationName" DefaultValue="{{OAuth-KV:organisation_name}}" AlwaysUseDefaultValue="true" />
</InputClaims>
<DisplayClaims>
<DisplayClaim ClaimTypeReferenceId="email" Required="true" />
<DisplayClaim ClaimTypeReferenceId="givenName" />
<DisplayClaim ClaimTypeReferenceId="surname" />
<DisplayClaim ClaimTypeReferenceId="jobTitle" />
<DisplayClaim ClaimTypeReferenceId="mobilePhone" />
<DisplayClaim ClaimTypeReferenceId="organisationName" />
<!-- Add password and confirm password fields to the UI -->
<DisplayClaim ClaimTypeReferenceId="password" Required="true" />
<DisplayClaim ClaimTypeReferenceId="confirmPassword" Required="true" />
</DisplayClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="email" Required="true" />
<OutputClaim ClaimTypeReferenceId="givenName" />
<OutputClaim ClaimTypeReferenceId="surname" />
<!-- Capture password and confirm password -->
<OutputClaim ClaimTypeReferenceId="password" Required="true" />
<OutputClaim ClaimTypeReferenceId="confirmPassword" Required="true" />
<OutputClaim ClaimTypeReferenceId="jobTitle" />
<OutputClaim ClaimTypeReferenceId="mobilePhone" />
<OutputClaim ClaimTypeReferenceId="organisationName" />
</OutputClaims>
<ValidationTechnicalProfiles>
<!-- Directly use PasswordMatchValidation for password matching -->
<ValidationTechnicalProfile ReferenceId="PasswordMatchValidation" />
<!-- Write user to Azure AD B2C after validation -->
<ValidationTechnicalProfile ReferenceId="AAD-UserWriteUsingLogonEmail" />
</ValidationTechnicalProfiles>
</TechnicalProfile>
<!-- Profile to Validate Password and Confirm Password Match -->
<TechnicalProfile Id="PasswordMatchValidation">
<DisplayName>Check if passwords match</DisplayName>
<Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.PasswordChangeProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<Metadata>
<Item Key="Operation">Match</Item>
<Item Key="RaiseErrorIfClaimsPrincipalAlreadyExists">false</Item>
<Item Key="RaiseErrorIfPasswordMismatch">true</Item>
<Item Key="UserMessageIfPasswordMismatch">The passwords do not match. Please try again.</Item>
</Metadata>
<InputClaims>
<InputClaim ClaimTypeReferenceId="password" Required="true" />
<InputClaim ClaimTypeReferenceId="confirmPassword" Required="true" />
</InputClaims>
</TechnicalProfile>
</TechnicalProfiles>
</ClaimsProvider>
<ClaimsProvider>
<DisplayName>Azure Active Directory</DisplayName>
<TechnicalProfiles>
<TechnicalProfile Id="AAD-UserWriteUsingLogonEmail">
<DisplayName>Write user to Azure AD B2C using email</DisplayName>
<Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.AzureActiveDirectory.AzureActiveDirectoryIdentityProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<Metadata>
<Item Key="Operation">Write</Item>
<Item Key="RaiseErrorIfClaimsPrincipalAlreadyExists">true</Item>
<Item Key="UserMessageIfClaimsPrincipalAlreadyExists">An account with this email already exists.</Item>
</Metadata>
<InputClaims>
<InputClaim ClaimTypeReferenceId="email" PartnerClaimType="signInNames.emailAddress" Required="true" />
<InputClaim ClaimTypeReferenceId="givenName" />
<InputClaim ClaimTypeReferenceId="surname" />
<InputClaim ClaimTypeReferenceId="password" PartnerClaimType="password" Required="true" />
</InputClaims>
<PersistedClaims>
<PersistedClaim ClaimTypeReferenceId="email" PartnerClaimType="signInNames.emailAddress" />
<PersistedClaim ClaimTypeReferenceId="givenName" />
<PersistedClaim ClaimTypeReferenceId="surname" />
<PersistedClaim ClaimTypeReferenceId="password" PartnerClaimType="password" />
</PersistedClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="objectId" />
</OutputClaims>
</TechnicalProfile>
</TechnicalProfiles>
</ClaimsProvider>
</ClaimsProviders>
<!-- User Journeys -->
<UserJourneys>
<UserJourney Id="SignUpJourney">
<OrchestrationSteps>
<!-- Self-asserted page to collect the user's information -->
<OrchestrationStep Order="1" Type="ClaimsExchange">
<ClaimsExchanges>
<ClaimsExchange Id="SelfAsserted-SignUp" TechnicalProfileReferenceId="SelfAsserted-SignUp" />
</ClaimsExchanges>
</OrchestrationStep>
<!-- Write the user to the directory -->
<OrchestrationStep Order="2" Type="ClaimsExchange">
<ClaimsExchanges>
<ClaimsExchange Id="AADUserWrite" TechnicalProfileReferenceId="AAD-UserWriteUsingLogonEmail" />
</ClaimsExchanges>
</OrchestrationStep>
<!-- Issue the claims in the token -->
<OrchestrationStep Order="3" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="JwtIssuer" />
</OrchestrationSteps>
</UserJourney>
</UserJourneys>
<RelyingParty>
<DefaultUserJourney ReferenceId="SignUpJourney" />
<TechnicalProfile Id="PolicyProfile">
<DisplayName>Sign Up Policy</DisplayName>
<Protocol Name="OpenIdConnect" />
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="objectId" PartnerClaimType="sub" />
<OutputClaim ClaimTypeReferenceId="email" />
<OutputClaim ClaimTypeReferenceId="givenName" />
<OutputClaim ClaimTypeReferenceId="surname" />
</OutputClaims>
<SubjectNamingInfo ClaimType="sub" />
</TechnicalProfile>
</RelyingParty>
</TrustFrameworkPolicy>
因此,经过“斗争”寻找解决方案后,我最终编辑了 Github 上启动包中的官方注册/登录
LocalAccounts
示例:自定义策略启动包
我更改了 TrustFrameworkBase 和 SignUpOrSignIn 文件(对于输出,Stack Overflow 不允许超过 30K 字符)。实现基本相同。在 TrustFrameworkBase 的 OrchestrationSteps 中,我做了它,因此它只显示第一步。有关详细信息,请参阅此处:如何在登录/注册示例中仅启用注册页面
TrustFrameworkBase 在
<TechnicalProfile Id="LocalAccountSignUpWithLogonEmail">
添加以下内容(将其替换为此):
<TechnicalProfile Id="LocalAccountSignUpWithLogonEmail">
<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="IncludeClaimResolvingInClaimsHandling">true</Item>
</Metadata>
<CryptographicKeys>
<Key Id="issuer_secret" StorageReferenceId="B2C_1A_TokenSigningKeyContainer" />
</CryptographicKeys>
<InputClaims>
<InputClaim ClaimTypeReferenceId="email" DefaultValue="{OAuth-KV:email}" AlwaysUseDefaultValue="true" />
<InputClaim ClaimTypeReferenceId="givenName" DefaultValue="{OAuth-KV:given_name}" AlwaysUseDefaultValue="true" />
<InputClaim ClaimTypeReferenceId="displayName" DefaultValue="{OAuth-KV:display_name}" AlwaysUseDefaultValue="true" />
<InputClaim ClaimTypeReferenceId="surname" DefaultValue="{OAuth-KV:surname}" AlwaysUseDefaultValue="true" />
<InputClaim ClaimTypeReferenceId="jobTitle" DefaultValue="{OAuth-KV:job_title}" AlwaysUseDefaultValue="true" />
<InputClaim ClaimTypeReferenceId="mobilePhone" DefaultValue="{OAuth-KV:mobile_phone}" AlwaysUseDefaultValue="true" />
<InputClaim ClaimTypeReferenceId="organisationName" DefaultValue="{OAuth-KV:organisation_name}" AlwaysUseDefaultValue="true" />
</InputClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="objectId" />
<OutputClaim ClaimTypeReferenceId="email" PartnerClaimType="Verified.Email" Required="true" />
<OutputClaim ClaimTypeReferenceId="newPassword" Required="true" />
<OutputClaim ClaimTypeReferenceId="reenterPassword" Required="true" />
<OutputClaim ClaimTypeReferenceId="executed-SelfAsserted-Input" DefaultValue="true" />
<OutputClaim ClaimTypeReferenceId="authenticationSource" />
<OutputClaim ClaimTypeReferenceId="newUser" />
<!-- Optional claims, to be collected from the user -->
<OutputClaim ClaimTypeReferenceId="displayName" />
<OutputClaim ClaimTypeReferenceId="givenName" />
<OutputClaim ClaimTypeReferenceId="surName" />
<OutputClaim ClaimTypeReferenceId="mobilePhone" />
<OutputClaim ClaimTypeReferenceId="jobTitle" />
<OutputClaim ClaimTypeReferenceId="organisationName" />
</OutputClaims>
<ValidationTechnicalProfiles>
<ValidationTechnicalProfile ReferenceId="AAD-UserWriteUsingLogonEmail" />
</ValidationTechnicalProfiles>
<UseTechnicalProfileForSessionManagement ReferenceId="SM-AAD" />
</TechnicalProfile>
注册或登录
<!-- Add the output claims you want if you want to reflect it: -->
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="displayName" />
<OutputClaim ClaimTypeReferenceId="givenName" />
<OutputClaim ClaimTypeReferenceId="surname" />
<OutputClaim ClaimTypeReferenceId="email" />
<OutputClaim ClaimTypeReferenceId="mobilePhone" />
<OutputClaim ClaimTypeReferenceId="jobTitle" />
<OutputClaim ClaimTypeReferenceId="organisationName" />
<OutputClaim ClaimTypeReferenceId="objectId" PartnerClaimType="sub"/>
<OutputClaim ClaimTypeReferenceId="tenantId" AlwaysUseDefaultValue="true" DefaultValue="{Policy:TenantObjectId}" />
</OutputClaims>
请确保还加载其他文件,例如入门包中的本地化和扩展!!!
将以下内容添加到自定义策略端点的 URL:
&[email protected]&given_name=TESTName&surname=SURNAMETest&job_title=INTERN TEST&mobile_phone=0682808840&organisation_name=Org Name&display_name=TEST DISPLAY&