Azure AD B2C Custom Policies using CAPTCHA for sign in means forgotten password flow fails with AADBC9990: Please complete CAPTCHA and retry

Richard Bergquist 20 Reputation points
2025-03-31T09:39:00.63+00:00

In Azure AD B2C I've implement CAPTCHA for sign in's using custom policies following the documentation in the B2C guides (https://learn.microsoft.com/en-us/azure/active-directory-b2c/add-captcha?pivots=b2c-custom-policy)

The policies are only configured to execute CAPTCHA for sign in. Not sign up.

    <!-- Added : CAPTCHA support -->
    <ClaimsProvider>
      <DisplayName>Set Captcha Feature Flags</DisplayName>
      <TechnicalProfiles>
        <TechnicalProfile Id="SetCaptchaFeatureFlags">
          <DisplayName>Set Feature Flags</DisplayName>
          <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.ClaimsTransformationProtocolProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
          <OutputClaims>
            <OutputClaim ClaimTypeReferenceId="signupCaptchaEnabled" DefaultValue="false" />
            <OutputClaim ClaimTypeReferenceId="signinCaptchaEnabled" DefaultValue="true" />
            <OutputClaim ClaimTypeReferenceId="mfaCaptchaEnabled" DefaultValue="false" />
          </OutputClaims>
        </TechnicalProfile>
      </TechnicalProfiles>
    </ClaimsProvider>

The sign page uses the sign in /sign up and forgotten password features together. CAPTCHA works fine on sign in. However if the sign up link or forgotten password link is followed then the flows goes to the very end before B2C errors with message on the page: "AADBC9990: Please complete CAPTCHA and retry"

There seems to be no way to disable CAPTCHA for the alternate flows off the sign up page.

In the technical profile that does the password reset I've tried to disable CAPTCHA and mark it as done as follows:


            <!-- Experiment: we are not doing captcha in this forgotten password flow , but we mark captcha as solved for this flow-->
            <OutputClaim ClaimTypeReferenceId="isCaptchaSolved" DefaultValue="true" AlwaysUseDefaultValue="true"/>  
            <OutputClaim ClaimTypeReferenceId="reason" DefaultValue="Solved" AlwaysUseDefaultValue="true"/> 

But to no avail. It seems once CAPTCHA is enabled in the sign in flow it must be completed for also the alternate flows off the page. Is there any advice to resolve this?

I note it works fine in the user flows and doesn't behave like this.

Microsoft Entra External ID
Microsoft Entra External ID
A modern identity solution for securing access to customer, citizen and partner-facing apps and services. It is the converged platform of Azure AD External Identities B2B and B2C. Replaces Azure Active Directory External Identities.
3,143 questions
0 comments No comments
{count} votes

Accepted answer
  1. Raja Pothuraju 21,125 Reputation points Microsoft External Staff
    2025-04-01T07:14:07.8833333+00:00

    Hello @Richard Bergquist,

    I'm glad that you were able to resolve your issue and thank you for posting your solution so that others experiencing the same thing can easily reference this! Since the Microsoft Q&A community has a policy that "The question author cannot accept their own answer. They can only accept answers by others ", I'll repost your solution in case you'd like to "Accept " the answer.

    Issue: Azure AD B2C Custom Policies using CAPTCHA for sign in means forgotten password flow fails with AADBC9990: Please complete CAPTCHA and retry

    Solution: Resolved by @Richard Bergquis.

    It turns out that if you enable any of the feature flags below then CAPTCHA will be checked and enforced for not only the main flow but all alternate flows of the main flow. So if you use a sign-in-sign-up-forgotten-password signin UX but enable 'signinCaptureEnabled' then CAPTCHA is required for the main sign in flow, plus sign-up plus forgotten-password. The solution is to turn off all these feature flags and only implement CAPTCHA on the pages actually required.

    <!-- Added : CAPTCHA support -->
        <ClaimsProvider>
          <DisplayName>Set Captcha Feature Flags</DisplayName>
          <TechnicalProfiles>
            <TechnicalProfile Id="SetCaptchaFeatureFlags">
              <DisplayName>Set Feature Flags</DisplayName>
              <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.ClaimsTransformationProtocolProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
              <OutputClaims>
                <!-- 
                  If these are turned on then captcha will be checked and enforced for not only the main flow but all alternate flows iff the main flow.
                  This means for a sign-in-sign-up user journey, captcha will be checked for the sign in, plus the sign up and forgotten  password 
                  alternate flows (which may not be desired).
                  If captcha is not intended for the alternate flows off the main flow then disable the feature flags for those main flows here, 
                  but implement the captcha controls only in the flows where it is intended to be used.
                  This is the reason why they are all set to false below. So captcha can be set in sign in, but not enforced off sign up or forgotten password alternate flows.
                -->
                <OutputClaim ClaimTypeReferenceId="signupCaptchaEnabled" DefaultValue="false" />
                <OutputClaim ClaimTypeReferenceId="signinCaptchaEnabled" DefaultValue="false" />
                <OutputClaim ClaimTypeReferenceId="mfaCaptchaEnabled" DefaultValue="false" />
              </OutputClaims>
            </TechnicalProfile>
          </TechnicalProfiles>
        </ClaimsProvider>
    
    

    If you have any other questions or are still running into more issues, please let me know. Thank you again for your time and patience throughout this issue.

    Please remember to "Accept Answer" if any answer/reply helped, so that others in the community facing similar issues can easily find the solution.

    0 comments No comments

1 additional answer

Sort by: Most helpful
  1. Richard Bergquist 20 Reputation points
    2025-03-31T20:44:21.0766667+00:00

    I've managed to answer my own question, but not in the way I expected. It turns out that if you enable any of the feature flags below then CAPTCHA will be checked and enforced for not only the main flow but all alternate flows of the main flow. So if you use a sign-in-sign-up-forgotten-password signin UX but enable 'signinCaptureEnabled' then CAPTCHA is required for the main sign in flow, plus sign-up plus forgotten-password. The solution is to turn off all these feature flags and only implement CAPTCHA on the pages actually required.

        <!-- Added : CAPTCHA support -->
        <ClaimsProvider>
          <DisplayName>Set Captcha Feature Flags</DisplayName>
          <TechnicalProfiles>
            <TechnicalProfile Id="SetCaptchaFeatureFlags">
              <DisplayName>Set Feature Flags</DisplayName>
              <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.ClaimsTransformationProtocolProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
              <OutputClaims>
                <!-- 
                  If these are turned on then captcha will be checked and enforced for not only the main flow but all alternate flows iff the main flow.
                  This means for a sign-in-sign-up user journey, captcha will be checked for the sign in, plus the sign up and forgotten  password 
                  alternate flows (which may not be desired).
                  If captcha is not intended for the alternate flows off the main flow then disable the feature flags for those main flows here, 
                  but implement the captcha controls only in the flows where it is intended to be used.
                  This is the reason why they are all set to false below. So captcha can be set in sign in, but not enforced off sign up or forgotten password alternate flows.
                -->
                <OutputClaim ClaimTypeReferenceId="signupCaptchaEnabled" DefaultValue="false" />
                <OutputClaim ClaimTypeReferenceId="signinCaptchaEnabled" DefaultValue="false" />
                <OutputClaim ClaimTypeReferenceId="mfaCaptchaEnabled" DefaultValue="false" />
              </OutputClaims>
            </TechnicalProfile>
          </TechnicalProfiles>
        </ClaimsProvider>
    
    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.