Guides & tutorials

Adaptive sign-up flow: fraud prevention with IP scoring and OTP

Import this tutorial scenario in your workspace
Table of contents

In this tutorial, we will cover how to build an adaptive signup flow, according to the risk score of the user’s password and the user’s IP scoring. This use case is meant to prevent spam accounts and avoid fraud, so it features an adaptive form that will generate a one-time password sent via email, if the IP scoring is considered high.

Key points of this sign-up flow

This use case features an adaptive, risk-based sign-up form. In the first place, the user’s password will be verified, in order to ensure top level security and avoid the usage of passwords that have been exposed or compromised. If the password is considered risky, the user will be informed and prompted to choose a stronger password.

On top of this, the user’s IP will be verified too, and its scoring will be used to trigger an additional security measure, if necessary. If the scoring is too high for our set standard, a one-time password will be generated and sent to the user’s email.

This way, spam or fraudulent accounts can be blocked at the earliest stage and the user’s email address will be verified. Keep in mind that if the scoring presents no risk, this additional step will not be executed, ensuring a minimal amount of friction. 

  • Signup with custom API
  • Adaptive, dynamic form
  • Password verification
  • Risk-based flow based on IP risk scoring
  • Email verification with one-time password 

1. Create a two-step form

In the forms editor, create two steps with the necessary fields. On the first step of the form, drag and drop the email and password fields from the left-side menu. On the second step of the form, add a text field so the user can enter their OTP, if necessary. Rename the fields to your taste, and add hint texts or labels, if necessary. 

Also keep in mind every field has its own ID, and these are used in order to reference variables. We will be modifying the fields’ IDs so they are descriptive, and these will be used later on when referencing variables. To know more about how to reference variables to return values, read our documentation on the matter.

2. First flow: Check password & IP risk, send OTP

In the Forms editor, go to the Flows section you can find on the left-side menu. There you can see an overview of your form and its flows. Add a first flow when the step 1 is being processed, and a second flow when step 2 is being processed. 

The first flow will first check if the password entered by the user is a safe one, has not been compromised or exposed. We will use the tool I Have I Been Pwned by calling its API.

After the password has been checked, the flow will continue to check the IP quality. To do so, we will use the fraud scoring tool IP Quality, by getting the results out of its API too. Depending on the results thrown, two different paths can be taken — the flow can finish by signing in the user or it will trigger an additional security action, the generation and sending a one-time password via email.

This is the overview of the first flow. We will now go through every action and its configuration.

2.1. Check the password security

In order to check the user’s password and its security, we will use the tool Have I Been Pwned. By calling its API, we can obtain advantageous information about the password entered by the user. If the user’s password has been exposed in a database leak or if it is too weak, an error message will be displayed prompting the user to use a stronger password, and the signup will not take place.

2.2. Check the IP risk

Now, we will call another third-party tool in order to check the reliability of the user’s IP. In this case, we will use IP Quality Score, a tool offering different services to tackle online fraud and spam. Specifically, we will be using the IP scoring feature, in order to determine a risk scoring and use it to measure the security of our signup flow. 

To configure this HTTP request, add the URL that determines the fraud scoring, and add the user’s own IP at the end of the URL by adding the proper reference. This is the result of the URL plus the IP reference:{{input.meta.ip}}

Select the GET method request and your secret API key under Headers. You can find it in your own account settings, and remember to keep it secret.

We will now add a conditional action that will determine if the IP scoring is safe or not. The score obtained goes from 0 to 100, indicating how probable the IP is fraudulent, abusive or is linked to malicious actions. We have selected 40 as the limit scoring for a secure IP. This action will check the IP fraud score and trigger two different actions, based on whether the result is higher or lower than 40.

Extra tip: When using risk scoring, 40 is considered the standard scoring for a secure IP. Some fraudulent activities are linked to scores between 70 and 75, while a scoring of +85 is considered a very high risk. 

To configure this action, add the reference {{checkIP.body.fraud_score}}, the condition "is less than", and the value 40, but you can edit this condition to meet your needs.

2.3. Generate one-time password

On the false branch, add the action Generate one-time password. This path will be executed if the result of the fraud scoring is superior to 40. 

To configure this action, add the reference {{}}. You can also personalize the number of digits of the one-time code, which is set as 4. 

Extra tip: In this use case, we are using a one-time password sent via email as an adaptive security method. Keep in mind that you can use other methods, such as magic links. 

2.4. Send email with one-time password

Next, add an email sending action. You can choose one from the native actions, or use the one powered by Arengu. This action will send an email to the user containing the one-time password. 

For the configuration of this action, a sendee reference {{}} is required, as well as a subject line, and the content of the email. Keep in mind, the email content supports HTML and you can use your own templates to personalize. Remember to include the reference {{generateOneTimePassword.code}} that will return the value of the OTP.

Extra tip: You can also send OPTs via SMS or with messaging apps, such as Telegram or WhatsApp.

2.5. Sign up with your own custom API

On the true branch, a signup action will be executed, since no risk will be detected. Add an HTTP request to sign in the user with your own custom API. Configure the action by adding your own parameters. In our case, this is our URL, we are selecting the POST method request and adding these references in the body:

  "sub": "{{}}",	
  "password": "{{input.body.password}}",

Under Headers, add your own API key.  

Then, add the If/then condition to check if the signup is successful or not. For its configuration, add the reference {{signupRequest.success}} and the condition is true.

2.6. Submit the form or show error message

Finally, add the actions Submit the form and Show error message. In order to display success or error messages respectively, add them in the corresponding fields.

In order to redirect the user with an open session, go to the Submit the form action and check the box Redirect to URL, and add the reference {{signupRequest.body.claim_url}}.

3. Second flow: Verify OTP and sign up 

This second flow takes place when the second step of the form is being processed, by verifying that the one-time code entered by the user is correct. If it is not, the user will see an error message. If the code is valid, the user will be signed up. 

This is what the second flow looks like. Now we will see every action and its details.

3.1.  Verify one-time password

We will use this action in order to verify that the code input is the same as the one generated in the previous step. The configuration of this action requires adding the reference value {{}} and the code value {{input.body.code}}

Following this action, an If/then condition action needs to be added, in order to verify that the code is valid and therefore execute different actions. If the code is not valid, an error message will be displayed. If the code is valid, the next action will sign up the user.

3.2. Sign up with your own custom API

To sign in the user with your custom API, an HTTP request action needs to be added and configured. For the setup, input your API URL, select the POST method for the request, and include your own parameters. In our case, these are:

  "sub": "{{}}",	
  "password": "{{input.body.password}}",

Under Headers, input your own API key. 

Then, add a conditional action to check if the signup action was executed correctly or not. On each branch, add an error message in case the signup was not successful and a Submit the form action to finalize the flow. 

The configuration of this action requires the reference {{signupRequest.success}} and the condition is true.

3.3. Submit the form or show error message

Lastly, add the final actions Submit the form and Show error message in the True and False branches, respectively. In the Submit the form action, you can specify a redirection and allow users to be logged in automatically after the signup is completed. To do so, simply check the box Redirect to URL, and add the reference {{signupRequest.body.claim_url}}

You might like to read

See more tutorials

Getting started with Arengu

Arengu allows you to build all your user flows connected to your current stack, and avoids coding all the UI, complex integrations, validations or logic from scratch. Try it for free and start building faster and scaling your application needs as they grow.