Azure AD B2C - 将电子邮件验证拆分并在两个屏幕中设置密码

问题描述 投票:0回答:1

我想将注册过程分为几个阶段,但为此我需要以某种方式订阅验证请求,然后根据结果我想显示下一阶段(或者如果未验证则显示错误)

有办法实现这个目标吗?

azure-active-directory azure-ad-b2c
1个回答
0
投票

是的,这可以使用自定义策略来实现。您需要将电子邮件验证拆分为单独的编排步骤,并为其添加一个 ClaimsProvider。您还需要使用只读电子邮件设置本地帐户注册的 ClaimsProvider。

幸运的是,有一个针对 Azure AD B2C 自定义策略的综合示例库,其中也存在这种特殊情况。 看这里。

以防链接失效,这里有一个完整的政策示例。此代码由 https://github.com/yoelhor 和其他可能的贡献者提供:

    <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_Demo_SignUp_SignIn_SplitEmailVerificationAndSignUp" 
  PublicPolicyUri="http://yourtenant.onmicrosoft.com/B2C_1A_Demo_SignUp_SignIn_SplitEmailVerificationAndSignUp">
  
  <BasePolicy>
    <TenantId>yourtenant.onmicrosoft.com</TenantId>
    <PolicyId>B2C_1A_TrustFrameworkExtensions</PolicyId>
  </BasePolicy>

  <BuildingBlocks>
    <ClaimsSchema>
      <!-- Read only email address to present to the user-->
      <ClaimType Id="readonlyEmail">
        <DisplayName>E-mail Address</DisplayName>
        <DataType>string</DataType>
        <UserInputType>Readonly</UserInputType>
      </ClaimType>
    </ClaimsSchema>
    <ClaimsTransformations>
      <ClaimsTransformation Id="CreateReadonlyEmailClaim" TransformationMethod="FormatStringClaim">
        <InputClaims>
          <InputClaim ClaimTypeReferenceId="email" TransformationClaimType="inputClaim" />
        </InputClaims>
        <InputParameters>
          <InputParameter Id="stringFormat" DataType="string" Value="{0}" />
        </InputParameters>
        <OutputClaims>
          <OutputClaim ClaimTypeReferenceId="readonlyEmail" TransformationClaimType="outputClaim" />
        </OutputClaims>
      </ClaimsTransformation>
    </ClaimsTransformations>

    <ContentDefinitions>
      <ContentDefinition Id="api.localaccount.emailVerification">
        <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.8</DataUri>
        <Metadata>
          <Item Key="DisplayName">Collect information from user page</Item>
        </Metadata>
        <LocalizedResourcesReferences MergeBehavior="Prepend">
          <LocalizedResourcesReference Language="en" LocalizedResourcesReferenceId="api.localaccount.emailVerification.en" />
        </LocalizedResourcesReferences>
      </ContentDefinition>
    </ContentDefinitions>

    <Localization Enabled="true">
      <SupportedLanguages DefaultLanguage="en" MergeBehavior="ReplaceAll">
        <SupportedLanguage>en</SupportedLanguage>
      </SupportedLanguages>
      <LocalizedResources Id="api.localaccount.emailVerification.en">
        <LocalizedStrings>
          <LocalizedString ElementType="UxElement" StringId="button_continue">Continue</LocalizedString>
        </LocalizedStrings>
      </LocalizedResources>
    </Localization>
  </BuildingBlocks>

  <ClaimsProviders>
    <ClaimsProvider>
      <DisplayName>Email Verification</DisplayName>
      <TechnicalProfiles>
        <!--Email verification only-->
        <TechnicalProfile Id="EmailVerification">
          <DisplayName>Initiate Email Address Verification For Local Account</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.localaccount.emailVerification</Item>
            <Item Key="language.button_continue">Continue</Item>
          </Metadata>
          <OutputClaims>
            <OutputClaim ClaimTypeReferenceId="email" PartnerClaimType="Verified.Email" Required="true" />
          </OutputClaims>
        </TechnicalProfile>
      </TechnicalProfiles>
    </ClaimsProvider>
    <ClaimsProvider>
      <DisplayName>Local Account</DisplayName>
      <TechnicalProfiles>
        <!--Sign-up self-asserted technical profile without Email verification-->
        <TechnicalProfile Id="LocalAccountSignUpWithReadOnlyEmail">
          <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">Create</Item>
            <!-- Remove sign-up email verification -->
            <Item Key="EnforceEmailVerification">False</Item>
          </Metadata>
          <InputClaimsTransformations>
            <InputClaimsTransformation ReferenceId="CreateReadonlyEmailClaim" />
          </InputClaimsTransformations>
          <InputClaims>
            <!--Sample: Set input the ReadOnlyEmail claim type to prefilled the email address-->
            <InputClaim ClaimTypeReferenceId="readOnlyEmail" />
          </InputClaims>
          <OutputClaims>
            <OutputClaim ClaimTypeReferenceId="objectId" />
            <!-- Sample: Display the ReadOnlyEmail claim type (instead of email claim type)-->
            <OutputClaim ClaimTypeReferenceId="readOnlyEmail" 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" />
          </OutputClaims>
          <ValidationTechnicalProfiles>
            <ValidationTechnicalProfile ReferenceId="AAD-UserWriteUsingLogonEmail" />
          </ValidationTechnicalProfiles>
          <!-- Sample: Disable session management for sign-up page -->
          <UseTechnicalProfileForSessionManagement ReferenceId="SM-Noop" />
        </TechnicalProfile>
      </TechnicalProfiles>
    </ClaimsProvider>
  </ClaimsProviders>
  <UserJourneys>
    <UserJourney Id="SignUpOrSignIn_Custom">
      <OrchestrationSteps>
        <OrchestrationStep Order="1" Type="CombinedSignInAndSignUp" ContentDefinitionReferenceId="api.signuporsignin">
          <ClaimsProviderSelections>
            <ClaimsProviderSelection ValidationClaimsExchangeId="LocalAccountSigninEmailExchange" />
          </ClaimsProviderSelections>
          <ClaimsExchanges>
            <ClaimsExchange Id="LocalAccountSigninEmailExchange" TechnicalProfileReferenceId="SelfAsserted-LocalAccountSignin-Email" />
          </ClaimsExchanges>
        </OrchestrationStep>

        <!-- Check if the user has selected to sign in using one of the social providers -->
        <OrchestrationStep Order="2" Type="ClaimsExchange">
          <Preconditions>
            <Precondition Type="ClaimsExist" ExecuteActionsIf="true">
              <Value>objectId</Value>
              <Action>SkipThisOrchestrationStep</Action>
            </Precondition>
          </Preconditions>
          <ClaimsExchanges>
            <ClaimsExchange Id="SignUpWithLogonEmailExchange_EmailVerification" TechnicalProfileReferenceId="EmailVerification" />
          </ClaimsExchanges>
        </OrchestrationStep>
        <OrchestrationStep Order="3" Type="ClaimsExchange">
          <Preconditions>
            <Precondition Type="ClaimsExist" ExecuteActionsIf="true">
              <Value>objectId</Value>
              <Action>SkipThisOrchestrationStep</Action>
            </Precondition>
          </Preconditions>
          <ClaimsExchanges>
            <ClaimsExchange Id="SignUpWithLogonEmailExchange_WithReadOnlyEmail" TechnicalProfileReferenceId="LocalAccountSignUpWithReadOnlyEmail" />
          </ClaimsExchanges>
        </OrchestrationStep>
        <OrchestrationStep Order="4" Type="ClaimsExchange">
          <ClaimsExchanges>
            <ClaimsExchange Id="AADUserReadWithObjectId" TechnicalProfileReferenceId="AAD-UserReadUsingObjectId" />
          </ClaimsExchanges>
        </OrchestrationStep>
        <OrchestrationStep Order="5" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="JwtIssuer" />
      </OrchestrationSteps>
    </UserJourney>
  </UserJourneys>

  <RelyingParty>
    <DefaultUserJourney ReferenceId="SignUpOrSignIn_Custom" />
    <TechnicalProfile Id="PolicyProfile">
      <DisplayName>PolicyProfile</DisplayName>
      <Protocol Name="OpenIdConnect" />
      <OutputClaims>
        <OutputClaim ClaimTypeReferenceId="displayName" />
        <OutputClaim ClaimTypeReferenceId="givenName" />
        <OutputClaim ClaimTypeReferenceId="surname" />
        <OutputClaim ClaimTypeReferenceId="email" />
        <OutputClaim ClaimTypeReferenceId="objectId" PartnerClaimType="sub"/>
        <OutputClaim ClaimTypeReferenceId="identityProvider" DefaultValue="" />
        <OutputClaim ClaimTypeReferenceId="tenantId" AlwaysUseDefaultValue="true" DefaultValue="{Policy:TenantObjectId}" />
      </OutputClaims>
      <SubjectNamingInfo ClaimType="sub" />
    </TechnicalProfile>
  </RelyingParty>
</TrustFrameworkPolicy>
© www.soinside.com 2019 - 2024. All rights reserved.