|
| 1 | +--- |
| 2 | +title: Enable CAPTCHA in Azure Active Directory B2C |
| 3 | +description: How to enable CAPTCHA for user flows and custom policies in Azure Active Directory B2C. |
| 4 | +author: kengaderdus |
| 5 | +manager: mwongerapk |
| 6 | +ms.service: active-directory |
| 7 | +ms.topic: how-to |
| 8 | +ms.date: 01/17/2024 |
| 9 | +ms.custom: project-no-code |
| 10 | +ms.author: kengaderdus |
| 11 | +ms.subservice: B2C |
| 12 | +zone_pivot_groups: b2c-policy-type |
| 13 | + |
| 14 | +#Customer intent: As a developer, I want to enable CAPTCHA in consumer-facing application that is secured by Azure Active Directory B2C, so that I can protect my sign-in and sign-up flows from automated attacks. |
| 15 | + |
| 16 | +--- |
| 17 | + |
| 18 | +# Enable CAPTCHA in Azure Active Directory B2C |
| 19 | + |
| 20 | +[!INCLUDE [active-directory-b2c-choose-user-flow-or-custom-policy](../../includes/active-directory-b2c-choose-user-flow-or-custom-policy.md)] |
| 21 | + |
| 22 | +Azure Active Directory B2C (Azure AD B2C) allows you to enable CAPTCHA prevent to automated attacks on your consumer-facing applications. Azure AD B2C’s CAPTCHA supports both audio and visual CAPTCHA challenges. You can enable this security feature in both sign-up and sign-in flows for your local accounts. CAPTCHA isn't applicable for social identity providers' sign-in. |
| 23 | + |
| 24 | +> [!NOTE] |
| 25 | +> This feature is in public preview |
| 26 | +
|
| 27 | +## Prerequisites |
| 28 | + |
| 29 | +[!INCLUDE [active-directory-b2c-customization-prerequisites](../../includes/active-directory-b2c-customization-prerequisites.md)] |
| 30 | + |
| 31 | +## Enable CAPTCHA |
| 32 | + |
| 33 | +::: zone pivot="b2c-user-flow" |
| 34 | + |
| 35 | +1. Sign in to the [Azure portal](https://portal.azure.com). |
| 36 | + |
| 37 | +1. If you have access to multiple tenants, select the **Settings** icon in the top menu to switch to your Azure AD B2C tenant from the **Directories + subscriptions** menu. |
| 38 | + |
| 39 | +1. In the left menu, select **Azure AD B2C**. Or, select **All services** and search for and select **Azure AD B2C**. |
| 40 | + |
| 41 | +1. Select **User flows**. |
| 42 | + |
| 43 | +1. Select the user flow for which you want to enable CAPTCHA. For example, *B2C_1_signinsignup*. |
| 44 | + |
| 45 | +1. Select **Properties**. |
| 46 | + |
| 47 | +1. Under **CAPTCHA (Preview)**, select the flow for which to enable CAPTCHA for, such as **Enable CAPTCHA - Sign Up**. |
| 48 | + |
| 49 | +1. Select **Save**. |
| 50 | + |
| 51 | +## Test the user flow |
| 52 | + |
| 53 | +Use the steps in [Test the user flow](tutorial-create-user-flows.md?pivots=b2c-user-flow#test-the-user-flow-1) to test and confirm that CAPTCHA is enabled for your chosen flow. You should be prompted to enter the characters you see or hear depending on the CAPTCHA type, visual or audio, you choose. |
| 54 | + |
| 55 | +::: zone-end |
| 56 | + |
| 57 | + |
| 58 | +::: zone pivot="b2c-custom-policy" |
| 59 | + |
| 60 | +To enable CAPTCHA in your custom policy, you need to update your existing custom policy files. If you don't have any existing custom policy files, [Download the .zip file](https://github.com/Azure-Samples/active-directory-b2c-custom-policy-starterpack/archive/master.zip) or clone the repository from `https://github.com/Azure-Samples/active-directory-b2c-custom-policy-starterpack`. In this article, we update the XML files in */Display Controls Starterpack/LocalAccounts/* folder. |
| 61 | + |
| 62 | +### Declare claims |
| 63 | + |
| 64 | +You need more claims to enable CAPTCHA in your custom policy: |
| 65 | + |
| 66 | +1. In VS Code, open the *TrustFrameworkBase.XML* file. |
| 67 | + |
| 68 | +1. In the `ClaimsSchema` section, declare claims by using the following code: |
| 69 | + |
| 70 | + ```xml |
| 71 | + <!--<ClaimsSchema>--> |
| 72 | + ... |
| 73 | + <ClaimType Id="inputSolution"> |
| 74 | + <DataType>string</DataType> |
| 75 | + </ClaimType> |
| 76 | + |
| 77 | + <ClaimType Id="solved"> |
| 78 | + <DataType>boolean</DataType> |
| 79 | + </ClaimType> |
| 80 | + |
| 81 | + <ClaimType Id="reason"> |
| 82 | + <DataType>string</DataType> |
| 83 | + </ClaimType> |
| 84 | + |
| 85 | + <ClaimType Id="azureregion"> |
| 86 | + <DataType>string</DataType> |
| 87 | + </ClaimType> |
| 88 | + |
| 89 | + <ClaimType Id="challengeId"> |
| 90 | + <DisplayName>The ID of the generated captcha</DisplayName> |
| 91 | + <DataType>string</DataType> |
| 92 | + <UserHelpText>Captcha challenge identifier</UserHelpText> |
| 93 | + <UserInputType>Paragraph</UserInputType> |
| 94 | + </ClaimType> |
| 95 | + |
| 96 | + <ClaimType Id="challengeType"> |
| 97 | + <DisplayName>Type of captcha (visual / audio)</DisplayName> |
| 98 | + <DataType>string</DataType> |
| 99 | + <UserHelpText>Captcha challenge type</UserHelpText> |
| 100 | + <UserInputType>Paragraph</UserInputType> |
| 101 | + </ClaimType> |
| 102 | + |
| 103 | + <ClaimType Id="challengeString"> |
| 104 | + <DisplayName>Captcha challenge code</DisplayName> |
| 105 | + <DataType>string</DataType> |
| 106 | + <UserHelpText>Captcha challenge code</UserHelpText> |
| 107 | + <UserInputType>Paragraph</UserInputType> |
| 108 | + </ClaimType> |
| 109 | + |
| 110 | + <ClaimType Id="captchaEntered"> |
| 111 | + <DisplayName>Captcha entered by the user</DisplayName> |
| 112 | + <DataType>string</DataType> |
| 113 | + <UserHelpText>Enter the characters you see</UserHelpText> |
| 114 | + <UserInputType>TextBox</UserInputType> |
| 115 | + </ClaimType> |
| 116 | + |
| 117 | + <ClaimType Id="isCaptchaSolved"> |
| 118 | + <DisplayName>Flag indicating that the captcha was successfully solved</DisplayName> |
| 119 | + <DataType>boolean</DataType> |
| 120 | + </ClaimType> |
| 121 | + ... |
| 122 | + <!--<ClaimsSchema>--> |
| 123 | + ``` |
| 124 | + |
| 125 | +### Configure a display control |
| 126 | + |
| 127 | +To enable CAPTCHA for your custom policy, you use a [CAPTCHA display Control](display-control-captcha.md). The CAPTCHA display control generates and renders the CAPTCHA image. |
| 128 | + |
| 129 | +In the *TrustFrameworkBase.XML* file, locate the `DisplayControls` element, then add the following display control as a child element. If you don't already have `DisplayControls` element, add one. |
| 130 | + |
| 131 | +```xml |
| 132 | +<!--<DisplayControls>--> |
| 133 | +... |
| 134 | +<DisplayControl Id="captchaControlChallengeCode" UserInterfaceControlType="CaptchaControl" DisplayName="Help us beat the bots"> |
| 135 | + <InputClaims> |
| 136 | + <InputClaim ClaimTypeReferenceId="challengeType" /> |
| 137 | + <InputClaim ClaimTypeReferenceId="challengeId" /> |
| 138 | + </InputClaims> |
| 139 | + |
| 140 | + <DisplayClaims> |
| 141 | + <DisplayClaim ClaimTypeReferenceId="challengeType" ControlClaimType="ChallengeType" /> |
| 142 | + <DisplayClaim ClaimTypeReferenceId="challengeId" ControlClaimType="ChallengeId" /> |
| 143 | + <DisplayClaim ClaimTypeReferenceId="challengeString" ControlClaimType="ChallengeString" /> |
| 144 | + <DisplayClaim ClaimTypeReferenceId="captchaEntered" ControlClaimType="CaptchaEntered" /> |
| 145 | + </DisplayClaims> |
| 146 | + |
| 147 | + <Actions> |
| 148 | + <Action Id="GetChallenge"> |
| 149 | + <ValidationClaimsExchange> |
| 150 | + <ValidationClaimsExchangeTechnicalProfile |
| 151 | + TechnicalProfileReferenceId="HIP-GetChallenge" /> |
| 152 | + </ValidationClaimsExchange> |
| 153 | + </Action> |
| 154 | + |
| 155 | + <Action Id="VerifyChallenge"> |
| 156 | + <ValidationClaimsExchange> |
| 157 | + <ValidationClaimsExchangeTechnicalProfile |
| 158 | + TechnicalProfileReferenceId="HIP-VerifyChallenge" /> |
| 159 | + </ValidationClaimsExchange> |
| 160 | + </Action> |
| 161 | + </Actions> |
| 162 | +</DisplayControl> |
| 163 | +... |
| 164 | +<!--</DisplayControls>--> |
| 165 | +``` |
| 166 | + |
| 167 | +### Configure a CAPTCHA technical profile |
| 168 | + |
| 169 | +Azure AD B2C [CAPTCHA technical profile](captcha-technical-profile.md) verifies the CAPTCHA challenge. This technical profile can generate a CAPTCHA code or verify it depending on how you configure it. |
| 170 | + |
| 171 | +In the *TrustFrameworkBase.XML* file, locate the `ClaimsProviders` element and add the claims provider by using the following code: |
| 172 | + |
| 173 | +```xml |
| 174 | +<!--<ClaimsProvider>--> |
| 175 | +... |
| 176 | +<ClaimsProvider> |
| 177 | + |
| 178 | + <DisplayName>HIPChallenge</DisplayName> |
| 179 | + |
| 180 | + <TechnicalProfiles> |
| 181 | + |
| 182 | + <TechnicalProfile Id="HIP-GetChallenge"> |
| 183 | + <DisplayName>GetChallenge</DisplayName> |
| 184 | + <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.CaptchaProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> |
| 185 | + <Metadata> |
| 186 | + <Item Key="Operation">GetChallenge</Item> |
| 187 | + <Item Key="Brand">HIP</Item> |
| 188 | + </Metadata> |
| 189 | + <InputClaims> |
| 190 | + <InputClaim ClaimTypeReferenceId="challengeType" /> |
| 191 | + </InputClaims> |
| 192 | + <DisplayClaims> |
| 193 | + <DisplayClaim ClaimTypeReferenceId="challengeString" /> |
| 194 | + </DisplayClaims> |
| 195 | + <OutputClaims> |
| 196 | + <OutputClaim ClaimTypeReferenceId="challengeId" /> |
| 197 | + <OutputClaim ClaimTypeReferenceId="challengeString" PartnerClaimType="ChallengeString" /> |
| 198 | + <OutputClaim ClaimTypeReferenceId="azureregion" /> |
| 199 | + </OutputClaims> |
| 200 | + </TechnicalProfile> |
| 201 | + <TechnicalProfile Id="HIP-VerifyChallenge"> |
| 202 | + <DisplayName>Verify Code</DisplayName> |
| 203 | + <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.CaptchaProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> |
| 204 | + <Metadata> |
| 205 | + <Item Key="Brand">HIP</Item> |
| 206 | + <Item Key="Operation">VerifyChallenge</Item> |
| 207 | + </Metadata> |
| 208 | + <InputClaims> |
| 209 | + <InputClaim ClaimTypeReferenceId="challengeType" DefaultValue="Visual" /> |
| 210 | + <InputClaim ClaimTypeReferenceId="challengeId" /> |
| 211 | + <InputClaim ClaimTypeReferenceId="captchaEntered" PartnerClaimType="inputSolution" Required="true" /> |
| 212 | + <InputClaim ClaimTypeReferenceId="azureregion" /> |
| 213 | + </InputClaims> |
| 214 | + <DisplayClaims> |
| 215 | + <DisplayClaim ClaimTypeReferenceId="captchaEntered" /> |
| 216 | + </DisplayClaims> |
| 217 | + <OutputClaims> |
| 218 | + <OutputClaim ClaimTypeReferenceId="challengeId" /> |
| 219 | + <OutputClaim ClaimTypeReferenceId="isCaptchaSolved" PartnerClaimType="solved" /> |
| 220 | + <OutputClaim ClaimTypeReferenceId="reason" PartnerClaimType="reason" /> |
| 221 | + </OutputClaims> |
| 222 | + </TechnicalProfile> |
| 223 | + </TechnicalProfiles> |
| 224 | +</ClaimsProvider> |
| 225 | +... |
| 226 | +<!--<ClaimsProviders>--> |
| 227 | +``` |
| 228 | + |
| 229 | +The CAPTCHA technical profile that you configure with the *GetChallenge* operation generates and display the CAPTCHA challenge string. The CAPTCHA technical profile that you configure with the *VerifyChallenge* verifies the challenge string that the user inputs. |
| 230 | + |
| 231 | +### Update content definition's page layouts |
| 232 | + |
| 233 | +For the various page layouts, use the following page layout versions: |
| 234 | + |
| 235 | +|Page layout |Page layout version range | |
| 236 | +|---------|---------| |
| 237 | +| Selfasserted | >=2.1.29 | |
| 238 | +| Unifiedssp | >=2.1.17 | |
| 239 | +| Multifactor | >=1.2.15 | |
| 240 | + |
| 241 | +**Example:** |
| 242 | + |
| 243 | +In the *TrustFrameworkBase.XML* file, under the `ContentDefinitions` element, locate a content definition with *Id="api.localaccountsignup"*, then updates its *DataUri* as shown in the following code: |
| 244 | + |
| 245 | +```xml |
| 246 | +<!---<ContentDefinitions>--> |
| 247 | +... |
| 248 | +<ContentDefinition Id="api.localaccountsignup"> |
| 249 | + ... |
| 250 | + <!--Update this DataUri--> |
| 251 | + <DataUri>urn:com:microsoft:aad:b2c:elements:contract:selfasserted:2.1.27</DataUri> |
| 252 | + ... |
| 253 | +</ContentDefinition> |
| 254 | +... |
| 255 | +<!---</ContentDefinitions>--> |
| 256 | +``` |
| 257 | +We specify the selfasserted page layout version as *2.1.27*. |
| 258 | + |
| 259 | +Once you configure your technical profiles and display controls, you can specify the flow for which you want to enable CAPTCHA. |
| 260 | + |
| 261 | +### Enable CAPTCHA for sign-up or sign-in flow |
| 262 | + |
| 263 | +To enable CAPTCHA for your sign-up or sign-in flow, use the following steps: |
| 264 | + |
| 265 | +1. Inspect your sign-up sign-in user journey, such as *SignUpOrSignIn*, to identify the self asserted technical profile that displays your sign-up or sign-in experience. |
| 266 | + |
| 267 | +1. In the technical profile, such as *LocalAccountSignUpWithLogonEmail*, add a metadata key and a display claim entry as shown in the following code: |
| 268 | + |
| 269 | +```xml |
| 270 | +<TechnicalProfile Id="LocalAccountSignUpWithLogonEmail"> |
| 271 | + ... |
| 272 | + <Metadata> |
| 273 | + ... |
| 274 | + <!--Add this metadata entry. Set value to true to activate CAPTCHA--> |
| 275 | + <Item Key="setting.enableCaptchaChallenge">true</Item> |
| 276 | + ... |
| 277 | + </Metadata> |
| 278 | + ... |
| 279 | + <DisplayClaims> |
| 280 | + ... |
| 281 | + <!--Add this display claim, which is a reference to the captcha display control--> |
| 282 | + <DisplayClaim DisplayControlReferenceId="captchaControlChallengeCode" /> |
| 283 | + ... |
| 284 | + </DisplayClaims> |
| 285 | + ... |
| 286 | +</TechnicalProfile> |
| 287 | +``` |
| 288 | +The display claim entry references the display control that you configured earlier. |
| 289 | + |
| 290 | +### Enable CAPTCHA in MFA flow |
| 291 | + |
| 292 | +To enable CAPTCHA in MFA flow, you need to make an update in two technical profiles, that is, in the self-asserted technical profile, and in the [phone factor technical profile](phone-factor-technical-profile.md): |
| 293 | + |
| 294 | +1. Inspect your sign-up sign-in user journey, such as *SignUpOrSignIn*, to identify the self-asserted technical profile and phone factor technical profiles that are responsible for your sign-up or sign-in flow. |
| 295 | + |
| 296 | +1. In both of the technical profiles, add a metadata key and a display claim entry as shown in the following code: |
| 297 | + |
| 298 | +```xml |
| 299 | +<TechnicalProfile Id="PhoneFactor-InputOrVerify"> |
| 300 | + ... |
| 301 | + <Metadata> |
| 302 | + ... |
| 303 | + <!--Add this metadata entry. Value set to true--> |
| 304 | + <Item Key="setting.enableCaptchaChallenge">true</Item> |
| 305 | + ... |
| 306 | + </Metadata> |
| 307 | + ... |
| 308 | + <DisplayClaims> |
| 309 | + ... |
| 310 | + <!--Add this display claim--> |
| 311 | + <DisplayClaim DisplayControlReferenceId="captchaControlChallengeCode" /> |
| 312 | + ... |
| 313 | + </DisplayClaims> |
| 314 | + ... |
| 315 | +</TechnicalProfile> |
| 316 | +``` |
| 317 | +::: zone-end |
| 318 | + |
| 319 | +> [!NOTE] |
| 320 | +> - You can't add CAPTCHA to an MFA step in a sign-up only user flow. |
| 321 | +> - In an MFA flow, CAPTCHA is applicable where the MFA method you select is SMS or phone call, SMS only or Phone call only. |
| 322 | +
|
| 323 | +::: zone pivot="b2c-user-flow" |
| 324 | +## Upload the custom policy files |
| 325 | + |
| 326 | +Use the steps in [Upload the policies](tutorial-create-user-flows.md?pivots=b2c-custom-policy&branch=pr-en-us-260336#upload-the-policies) to upload your custom policy files. |
| 327 | + |
| 328 | +## Test the custom policy |
| 329 | + |
| 330 | +Use the steps in [Test the custom policy](tutorial-create-user-flows.md?pivots=b2c-custom-policy#test-the-custom-policy) to test and confirm that CAPTCHA is enabled for your chosen flow. You should be prompted to enter the characters you see or hear depending on the CAPTCHA type, visual or audio, you choose. |
| 331 | +::: zone-end |
| 332 | + |
| 333 | +## Next steps |
| 334 | + |
| 335 | +- Learn how to [Define a CAPTCHA technical profile](captcha-technical-profile.md). |
| 336 | +- Learn how to [Configure CAPTCHA display control](display-control-captcha.md). |
0 commit comments