azure-active-directoryazure-ad-b2cazure-ad-b2c-custom-policyforgot-password

Sign in with username and reset password with only email for a B2C custom policy


I am using a custom B2C policy. when I register, I insert email, username and password. When I sign in, I sign in with username. When I reset password, I reset password with only email,but just here I have to next error message:

enter image description here

I believe that the email not match with username, but I want reset password only email. What XML tag should I to setting?

MY RESETPASSWORD.XML

  <BasePolicy>
    <TenantId>XXXXXXXXXX.onmicrosoft.com</TenantId>
    <PolicyId>B2C_1A_TrustFrameworkExtensions</PolicyId>
  </BasePolicy>
  <RelyingParty>
    <DefaultUserJourney ReferenceId="PasswordChange" />
    <TechnicalProfile Id="PolicyProfile">
      <DisplayName>PolicyProfile</DisplayName>
      <Protocol Name="OpenIdConnect" />
      <OutputClaims>
        <OutputClaim ClaimTypeReferenceId="email" />
        <OutputClaim ClaimTypeReferenceId="objectId" PartnerClaimType="sub" />
        <OutputClaim ClaimTypeReferenceId="tenantId" AlwaysUseDefaultValue="true" DefaultValue=" 
            {Policy:TenantObjectId}" />
      </OutputClaims>
      <SubjectNamingInfo ClaimType="sub" />
    </TechnicalProfile>
  </RelyingParty>

MY TRUSTFRAMWORKEXTENTIONS.XML => REGISTER

<TechnicalProfile Id="AAD-UserWriteUsingLogonName">
                    <Metadata>
                        <Item Key="Operation">Write</Item>
                        <Item Key="RaiseErrorIfClaimsPrincipalAlreadyExists">true</Item>
                    </Metadata>
                    <InputClaims>
                        <InputClaim ClaimTypeReferenceId="signInName" PartnerClaimType="signInNames.userName" Required="true" />
                    </InputClaims>
                    <PersistedClaims>
                        <PersistedClaim ClaimTypeReferenceId="signInName" PartnerClaimType="signInNames.userName" />
                        <PersistedClaim ClaimTypeReferenceId="email" PartnerClaimType="strongAuthenticationEmailAddress" />
                        <PersistedClaim ClaimTypeReferenceId="newPassword" PartnerClaimType="password" />
                        <PersistedClaim ClaimTypeReferenceId="displayName" DefaultValue="SomeDefaultDisplayNameValue" />
                         <!-- <PersistedClaim ClaimTypeReferenceId="CodigoVerificacion" />  -->
                        <!-- <PersistedClaim ClaimTypeReferenceId="surname" /> -->
                    </PersistedClaims>
                    <OutputClaims>
                        <OutputClaim ClaimTypeReferenceId="objectId" />
                        <!-- <OutputClaim ClaimTypeReferenceId="newUser" PartnerClaimType="newClaimsPrincipalCreated" /> -->
                        <OutputClaim ClaimTypeReferenceId="authenticationSource" DefaultValue="localAccountAuthentication" />
                        <OutputClaim ClaimTypeReferenceId="userPrincipalName" />
                    </OutputClaims>
                    <IncludeTechnicalProfile ReferenceId="AAD-Common" />
                    <UseTechnicalProfileForSessionManagement ReferenceId="SM-AAD" />
        </TechnicalProfile>
            <TechnicalProfile Id="LocalAccountSignUpWithLogonName">
                    <DisplayName>User ID 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="LocalAccountType">Username</Item>
                        <Item Key="LocalAccountProfile">true</Item>
                        <Item Key="language.button_continue">Registrase</Item>
                        <!-- desactivar validar correo -->
                         <Item Key="EnforceEmailVerification">false</Item>
                    </Metadata>
                    <InputClaims>
                        <InputClaim ClaimTypeReferenceId="signInName" />
                    </InputClaims>
                    <OutputClaims>
                        <OutputClaim ClaimTypeReferenceId="objectId" Required="true" />
                        <OutputClaim ClaimTypeReferenceId="signInName" Required="true" />
                        <OutputClaim ClaimTypeReferenceId="newPassword" Required="true" />
                        <OutputClaim ClaimTypeReferenceId="reenterPassword" Required="true" />
                        <OutputClaim ClaimTypeReferenceId="email" PartnerClaimType="Verified.Email" Required="true" />
                        <OutputClaim ClaimTypeReferenceId="executed-SelfAsserted-Input" DefaultValue="true" />
                        <!-- <OutputClaim ClaimTypeReferenceId="CodigoVerificacion" Required="true" /> -->
                        <!-- <OutputClaim ClaimTypeReferenceId="newUser" /> -->
                        <OutputClaim ClaimTypeReferenceId="authenticationSource" />
                        <OutputClaim ClaimTypeReferenceId="userPrincipalName" />
                        <!-- <OutputClaim ClaimTypeReferenceId="surname" Required="true" /> -->
                    </OutputClaims>
                    <ValidationTechnicalProfiles>
                        <ValidationTechnicalProfile ReferenceId="AAD-UserWriteUsingLogonName" />
                    </ValidationTechnicalProfiles>
                    <UseTechnicalProfileForSessionManagement ReferenceId="SM-AAD" />
                </TechnicalProfile>

MY TRUSTFRAMWORKEXTENTIONS.XML => FORGOT PASSWORD

nter code here
    <!-- Check if the user has selected forgot password herehere hereherehere-->
                        <OrchestrationStep Order="3" Type="InvokeSubJourney">
                            <Preconditions>
                                <Precondition Type="ClaimsExist" ExecuteActionsIf="false">
                                <Value>isForgotPassword</Value>
                                <Action>SkipThisOrchestrationStep</Action>
                                </Precondition>
                            </Preconditions>
                            <JourneyList>
                                <Candidate SubJourneyReferenceId="PasswordReset" />
                            </JourneyList>
                        </OrchestrationStep>

<SubJourneys>
        <SubJourney Id="PasswordReset" Type="Call">
        <OrchestrationSteps>
            <!-- Validate user's email address. Run this step only when user resets the password-->
            <OrchestrationStep Order="1" Type="ClaimsExchange">
            <ClaimsExchanges>
                <ClaimsExchange Id="PasswordResetUsingEmailAddressExchange" TechnicalProfileReferenceId="LocalAccountDiscoveryUsingEmailAddress" />
            </ClaimsExchanges>
            </OrchestrationStep>

            <!-- Collect and persist a new password. Run this step only when user resets the password-->
            <OrchestrationStep Order="2" Type="ClaimsExchange">
            <ClaimsExchanges>
                <ClaimsExchange Id="NewCredentials" TechnicalProfileReferenceId="LocalAccountWritePasswordUsingObjectId" />
            </ClaimsExchanges>
            </OrchestrationStep>
        </OrchestrationSteps>
        </SubJourney>
     </SubJourneys>

When I register, my email does not save. What am I doing wrong?

enter image description here


Solution

  • If you created the user with a username and didn't capture the email then you can't use the standard password reset because that is based on email.

    Look at this policy - it shows how to use username or email.

    But beware. Email is preferred for security because you can ask the user to verify the email. The only way to verify username is to use MFA and ask the user e.g. to enter the SMS OTP.

    That's why you should always capture the email when you signup with username.