简体   繁体   English

通过使用 SendGrid 的单独 email 验证注册定制

[英]Sign up customization with separate email verification using SendGrid

I am using Azure AD B2C with Custom Policies to implement a sign-up flow where user has to verify the email before proceeds to sign up page.我正在使用 Azure AD B2C 和自定义策略来实施注册流程,用户必须在继续注册页面之前验证 email。

I found an example here https://github.com/azure-ad-b2c/samples/blob/master/policies/split-email-verification-and-signup/policy/SignUpOrSignIn_SplitEmailVerificationAndSignUp.xml#L61-L77 and I try to modify this code and add a DisplayControl and from there I implement the custom email verification flow.我在这里找到了一个例子https://github.com/azure-ad-b2c/samples/blob/master/policies/split-email-verification-and-signup/policy/SignUpOrSignIn_SplitEmailVerificationAndSignUp.xml#L61-L77我尝试修改此代码并添加一个 DisplayControl,然后我从那里实现自定义 email 验证流程。

The emailVerificationControl is also based on the other sample code found here https://github.com/azure-ad-b2c/samples/blob/master/policies/custom-email-verifcation-displaycontrol/policy/SendGrid/DisplayControl_TrustFrameworkExtensions.xml#L142-L163 emailVerificationControl也基于此处找到的其他示例代码https://github.com/azure-ad-b2c/samples/blob/master/policies/custom-email-verifcation-displaycontrol/policy/SendGrid/DisplayControl_TrustFrameworkExtensions.xml# L142-L163

<BuildingBlocks>
    <ClaimsSchema>
      <ClaimType Id="readonlyEmail">
        <DisplayName>E-mail Address</DisplayName>
        <DataType>string</DataType>
        <UserInputType>Readonly</UserInputType>
      </ClaimType>
      <ClaimType Id="isForgotPassword">
        <DisplayName>isForgotPassword</DisplayName>
        <DataType>boolean</DataType>
        <AdminHelpText>Whether the user has clicked Forgot Password</AdminHelpText>
      </ClaimType>
      <ClaimType Id="termsOfUseConsentChoice">
        <DisplayName></DisplayName>
        <DataType>string</DataType>
        <UserInputType>CheckboxMultiSelect</UserInputType>
        <Restriction>
          <Enumeration Text=" I agree to the Terms Of Service" Value="AgreeToTermsOfUseConsentYes" SelectByDefault="false" />
        </Restriction>
      </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>
  </BuildingBlocks>
  <ClaimsProviders>
    <ClaimsProvider>
      <DisplayName>Email Verification</DisplayName>
      <TechnicalProfiles>
        <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.localaccountsignup</Item>
            <Item Key="language.button_continue">Continue</Item>
          </Metadata>
          <DisplayClaims>
            <DisplayClaim DisplayControlReferenceId="emailVerificationControl" />
          </DisplayClaims>
          <CryptographicKeys>
            <Key Id="issuer_secret" StorageReferenceId="B2C_1A_TokenSigningKeyContainer" />
          </CryptographicKeys>
          <IncludeInSso>false</IncludeInSso>
          <InputClaims>
            <InputClaim ClaimTypeReferenceId="email" />
          </InputClaims>
          <OutputClaims>
            <OutputClaim ClaimTypeReferenceId="email" PartnerClaimType="Verified.Email" Required="true" />
          </OutputClaims>
        </TechnicalProfile>
      </TechnicalProfiles>
    </ClaimsProvider>

    <ClaimsProvider>
      <DisplayName>Local Account</DisplayName>
      <TechnicalProfiles>
        <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>
            <Item Key="EnforceEmailVerification">False</Item>
          </Metadata>
          <InputClaimsTransformations>
            <InputClaimsTransformation ReferenceId="CreateReadonlyEmailClaim" />
          </InputClaimsTransformations>
          <InputClaims>
            <InputClaim ClaimTypeReferenceId="readOnlyEmail" />
            <InputClaim ClaimTypeReferenceId="termsOfUseConsentChoice" DefaultValue="AgreeToTermsOfUseConsentNo" />
          </InputClaims>
          <OutputClaims>
            <OutputClaim ClaimTypeReferenceId="objectId" />
            <OutputClaim ClaimTypeReferenceId="readOnlyEmail" Required="true" />
            <OutputClaim ClaimTypeReferenceId="newPassword" Required="true" />
            <OutputClaim ClaimTypeReferenceId="reenterPassword" Required="true" />
            <OutputClaim ClaimTypeReferenceId="termsOfUseConsentChoice" Required="true" />
            <OutputClaim ClaimTypeReferenceId="executed-SelfAsserted-Input" DefaultValue="true" />
            <OutputClaim ClaimTypeReferenceId="authenticationSource" />
            <OutputClaim ClaimTypeReferenceId="newUser" />
          </OutputClaims>
          <ValidationTechnicalProfiles>
            <ValidationTechnicalProfile ReferenceId="AAD-UserWriteUsingLogonEmail" />
          </ValidationTechnicalProfiles>
          <!-- Sample: Disable session management for sign-up page -->
          <UseTechnicalProfileForSessionManagement ReferenceId="SM-Noop" />
        </TechnicalProfile>
        <TechnicalProfile Id="ForgotPassword">
          <DisplayName>Forgot your password?</DisplayName>
          <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.ClaimsTransformationProtocolProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
          <OutputClaims>
            <OutputClaim ClaimTypeReferenceId="isForgotPassword" DefaultValue="true" AlwaysUseDefaultValue="true" />
          </OutputClaims>
        </TechnicalProfile>
        <TechnicalProfile Id="SelfAsserted-LocalAccountSignin-Email">
          <Metadata>
            <Item Key="setting.forgotPasswordLinkOverride">ForgotPasswordExchange</Item>
          </Metadata>
        </TechnicalProfile>
      </TechnicalProfiles>
    </ClaimsProvider>
  </ClaimsProviders>
  <UserJourneys>
    <UserJourney Id="SignUpOrSignIn_Custom">
      <OrchestrationSteps>
        <OrchestrationStep Order="1" Type="CombinedSignInAndSignUp" ContentDefinitionReferenceId="api.signuporsignin">
          <ClaimsProviderSelections>
            <ClaimsProviderSelection ValidationClaimsExchangeId="LocalAccountSigninEmailExchange" />
            <ClaimsProviderSelection TargetClaimsExchangeId="ForgotPasswordExchange" />
          </ClaimsProviderSelections>
          <ClaimsExchanges>
            <ClaimsExchange Id="LocalAccountSigninEmailExchange" TechnicalProfileReferenceId="SelfAsserted-LocalAccountSignin-Email" />
          </ClaimsExchanges>
        </OrchestrationStep>

        <OrchestrationStep Order="2" Type="ClaimsExchange">
          <Preconditions>
            <Precondition Type="ClaimsExist" ExecuteActionsIf="true">
              <Value>objectId</Value>
              <Action>SkipThisOrchestrationStep</Action>
            </Precondition>
          </Preconditions>
          <ClaimsExchanges>
            <ClaimsExchange Id="SignUpWithLogonEmailExchange" TechnicalProfileReferenceId="EmailVerification" />
            <ClaimsExchange Id="ForgotPasswordExchange" TechnicalProfileReferenceId="ForgotPassword" />
          </ClaimsExchanges>
        </OrchestrationStep>
        <OrchestrationStep Order="3" Type="ClaimsExchange">
          <Preconditions>
            <Precondition Type="ClaimsExist" ExecuteActionsIf="true">
              <Value>objectId</Value>
              <Action>SkipThisOrchestrationStep</Action>
            </Precondition>
            <Precondition Type="ClaimsExist" ExecuteActionsIf="true">
              <Value>isForgotPassword</Value>
              <Action>SkipThisOrchestrationStep</Action>
            </Precondition>
          </Preconditions>
          <ClaimsExchanges>
            <ClaimsExchange Id="LocalAccountSignUpWithReadOnlyEmail" TechnicalProfileReferenceId="LocalAccountSignUpWithReadOnlyEmail" />
          </ClaimsExchanges>
        </OrchestrationStep>

        <OrchestrationStep Order="4" Type="InvokeSubJourney">
          <Preconditions>
            <Precondition Type="ClaimsExist" ExecuteActionsIf="false">
              <Value>isForgotPassword</Value>
              <Action>SkipThisOrchestrationStep</Action>
            </Precondition>
          </Preconditions>
          <JourneyList>
            <Candidate SubJourneyReferenceId="PasswordReset" />
          </JourneyList>
        </OrchestrationStep>

        <OrchestrationStep Order="5" Type="ClaimsExchange">
          <ClaimsExchanges>
            <ClaimsExchange Id="AADUserReadWithObjectId" TechnicalProfileReferenceId="AAD-UserReadUsingObjectId" />
          </ClaimsExchanges>
        </OrchestrationStep>
        <OrchestrationStep Order="6" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="JwtIssuer" />
      </OrchestrationSteps>
    </UserJourney>
  </UserJourneys>
  <SubJourneys>
    <SubJourney Id="PasswordReset" Type="Call">
      <OrchestrationSteps>
        <OrchestrationStep Order="1" Type="ClaimsExchange">
          <ClaimsExchanges>
            <ClaimsExchange Id="PasswordResetUsingEmailAddressExchange" TechnicalProfileReferenceId="LocalAccountDiscoveryUsingEmailAddress" />
          </ClaimsExchanges>
        </OrchestrationStep>

        <OrchestrationStep Order="2" Type="ClaimsExchange">
          <ClaimsExchanges>
            <ClaimsExchange Id="NewCredentials" TechnicalProfileReferenceId="LocalAccountWritePasswordUsingObjectId" />
          </ClaimsExchanges>
        </OrchestrationStep>
      </OrchestrationSteps>
    </SubJourney>
  </SubJourneys>
  <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>

Everything seems working fine so far.到目前为止,一切似乎都运行良好。 I can enter my email address and it will send the code using via SendGrid, I can click verify code button and it successfully verified and has a continue button.我可以输入我的 email 地址,它将使用 SendGrid 发送代码,我可以单击验证代码按钮,它成功验证并有一个继续按钮。

1. The DisplayControl 1. 显示控件

2. Send code to email address 2.发送代码到email地址

3. Verify email address and continue 3.验证email地址并继续

But after I click the continue button the page just crash and says, "The page cannot be displayed because an internal server error has occured."但是当我点击继续按钮后,页面就崩溃了,并说“页面无法显示,因为发生了内部服务器错误。”

4. Sign up page does not show up, it crashed 4.注册页面不显示,崩溃了

The only changes I made is the DisplayControl and it works fine without it (which in this case it uses the Microsoft's default email verification service) so I suppose there is something I did wrong...I would like to get some help if anyone has done anything similar with Azure AD B2C before.我所做的唯一更改是DisplayControl ,没有它它可以正常工作(在这种情况下,它使用 Microsoft 的默认 email 验证服务)所以我想我做错了什么......如果有人有,我想得到一些帮助之前做过与 Azure AD B2C 类似的事情。

Thanks a lot in advance for your help!非常感谢您的帮助!

Solved in this github issue: https://github.com/azure-ad-b2c/samples/issues/193在此 github 问题中解决: https://github.com/azure-ad-b2c/samples/issues/193

If you are using the following samples Split Email Verification and Custom Email Verification .如果您使用以下示例拆分 Email 验证自定义 Email 验证

The only changes required from these sample policies is that you change the Output Claim from这些示例策略所需的唯一更改是将 Output 声明从

<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.localaccountsignup</Item>
   <Item Key="language.button_continue">Continue</Item>
  </Metadata>
  <InputClaims>
    <InputClaim ClaimTypeReferenceId="email" />
  </InputClaims>
  <DisplayClaims>
    <DisplayClaim DisplayControlReferenceId="emailVerificationControl" />
  </DisplayClaims>
  <OutputClaims>
<!----------- CHANGE THIS LINE ------------------------------->
     <OutputClaim ClaimTypeReferenceId="email" PartnerClaimType="Verified.Email" Required="true" />
  </OutputClaims>
</TechnicalProfile>
<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.localaccountsignup</Item>
   <Item Key="language.button_continue">Continue</Item>
  </Metadata>
  <InputClaims>
    <InputClaim ClaimTypeReferenceId="email" />
  </InputClaims>
  <DisplayClaims>
    <DisplayClaim DisplayControlReferenceId="emailVerificationControl" />
  </DisplayClaims>
  <OutputClaims>
<!----------- TO THIS LINE ------------------------------->
    <OutputClaim ClaimTypeReferenceId="email" Required="true" />
  </OutputClaims>
</TechnicalProfile>

I also noticed this must be added to the following technical profiles: [EmailVerification, LocalAccountDiscoveryUsingEmailAddress]我还注意到这必须添加到以下技术配置文件中:[EmailVerification, LocalAccountDiscoveryUsingEmailAddress]

<InputClaims>
   <InputClaim ClaimTypeReferenceId="email" />
</InputClaims>

The UserJourney should look like UserJourney 应该看起来像

  • EmailVerification电子邮件验证
  • LocalAccountSignUpWithReadOnlyEmail LocalAccountSignUpWithReadOnlyEmail
  • AAD-UserReadUsingObjectId AAD-UserReadUsingObjectId
  • JwtIssuer Jwt发行人

PS: It's also important to note that your ContentDefinitions must be version greater than 2.0.0. PS:同样重要的是要注意您的 ContentDefinitions 版本必须大于 2.0.0。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM