Skip to content
  • There are no suggestions because the search field is empty.

Two-factor authentication setup

Configure the two-factor authentication to add a vital layer of security to your application

This guide will help you to secure your application with two-factor authentication (2FA). By setting up data models, authentication profiles, roles, and specific actions, you can significantly reduce unauthorized access. Let's get started on building this key security feature.

Note: It's highlt recommended to set up your mail configuration before setting up your two-factor authentication functionality. Here is a guide to do so.

Create the necessary data models

The first thing we have to do is create the necessary three data models with the following properties:

  1. Temporary WebUser: Email address, Password
  2. WebUser: Email address, Password
  3. Token: Token (Text (single-line)), TokenType (Text (single-line) / optional, only if you plan to use the token model for multiple purposes e.g. password reset, 2FA etc.), Token expiration (Date time / optional but highly recommended)

Now set up a relation between Token and WebUser models to a Many-to-one (many Tokens belong to one WebUser):

Set up your tools

1. Add an authentication profile, call it Temporary WebUser and set it up as follows:

2. Also, set up an authentication profile for WebUser, set it up as follows:

3. Go to Configurations and create a new configuration called ‘is_sandbox’ , set it to ‘Single’ under the Kind option and set the value true for all the sandboxes, set it to false in your production application. 

(This isn’t a necessary step and can be skipped but it is highly recommended for speeding up your testing).

4. Open roles and permissions and add a new role, called Temporary WebUser.

Configure the Read permissions to disallow access to all except for ‘token’ and ‘Temporary WebUser’, which will be set to filtered for security purposes.

Set the token filter to ‘Token.WebUser.Id’ equals ‘current_web_user.Id’ and set the Temporary WebUser filter to ‘Temporary WebUser.Id’ equals current_temporary_webuser.Id’.

Adjusting / creating the login action

The initial action we will develop generates a token and dispatches an email to the user once the correct credentials are provided.

Before we start working on the login action, create a new page to ask the user their 2FA-code. Create an authenticated page with Temporary WebUser as the authentication profile. After creating this page, go back to the login page and update the login form so that on login, the user gets redirected to the newly created page.

Now we can finally get into making the action!

1. First, set the input variables to:

  • Email (text)
  • Password (text)

And create an action variable in the Start step:

  • Jwt (text)

2. After doing this, we can add the first action step - Condition. It checks if the two input variables (‘email_adress’  and ‘password’) exist. If they don’t, we’ll raise an error, and if they do, we can continue with our action.

3. Add a Try / Catch (we use Try/Catch so we can give back a custom error message to the user if something goes wrong) with the result put to ‘auth_result’, set your custom error message to ERROR (or whatever you want to display in your logs).

4. Within the Try / Catch, you have to put the Authenticate User step. 

In the Authenticate User step, set the authentication profile to the Temporary WebUser profile we made earlier. The username and password should be the input variables. In the As option select the ‘jwt’ action variable that we have defined at the Start (if you don't do this, the login interaction on your login page will not work).


5. Now put in a last condition to check if there was an error by checking if your ‘auth_result’ equals ERROR (or what your own custom error message was). If so, raise an error, otherwise send an email with a 2FA code. 

Do this by creating the Sub Action we create later on in the document. Send an input variable called email with the value set to ‘email_address’ (input variable) to the Sub Action.

6. Finally, make sure that in the Finish step, you again select the ‘jwt’ action variable as the output variable. Otherwise, the JWT token won't be passed back to the page and you can’t log in.

If everything went correctly, your action should look something like this:

 



Generate token / send email sub-action

1. Set the input variables to:

  • Email (text)

And create an action variable: 

  • WebUser_obj (object, uses the WebUser model, set up the filter rule that webuser.email_address equals email (input variable) )

2. Use your preferred way of generating a token, we use the Generate random number step for this example.

Also, we set a minimum of 10000 and a maximum of 99999 in this step so that there always is a 5-numbered code. Name the result ‘random_2FA_code’  

3. After this step, put in an expression that will turn your random 2fa code into a string so that your code will remain the same as we go through the steps. Set the result to 2FA_code_text

4. Before creating a new token, we’ll have to delete any tokens the user has previously requested, do this by dragging in a Delete Many Records step and under the collection opties select webuser_obj.tokens.


5. The last thing we’ll do is set an expiration date/time for our token so it doesn’t stay valid indefinitely. Do this by dragging in a Date/time offset step. Set the offset to your desired time, for this example we’ll use an offset of 1 hour. Set the result to token_expiration.

6. Now drag in a Create record step for the token model with the token properties set to the following:

After creating the record for the token, you can send out a mail containing the token/2FA code. If you're not sure how to set up a mail service, follow the steps in this article.

Creating the 2FA-code verification action

1. Onto the action steps, start off by going into the Start step and make sure it has one input variable and one action variable: 

  • Input variable: text_code (text)
  • Action variable: Jwt (text)

2. Drag in a Condition step and in there, add a variable. Call it ‘token’ and use an object with the Token model. Set up the following filter rule:

‘Token’ equals ‘text_code’ and ‘web_user.email_address’ equals ‘current_temporary_webuser.email’

 

Now for the filtering, check if the current_temporary_webuser exists. If it doesn’t, raise an error, if the current_temporary_webuser does exist we can go on.

3. Add an expression for the sandbox_code, do this by dragging the Expression step and setting the expression to the desired code (We recommend something easy since this code can only be used in sandboxes for testing purposes. We went for “00000”) and name the result “sandbox_code”.

4. Before we go on we have to add another Date/Time offset step. This one is to check if the token hasn’t yet expired so we’ll set the offset to 1 second and set the result to ‘now’

5. After the Date/Time offset, drag in another Condition step. This one will check if the user even entered a 2FA Code and if the expiration date has not been passed yet, we do this by checking if the text_code exists.

We also have to see if the Token exists and the expiration date is after or at now. If it doesn’t, we’ll raise an error, if the user did enter a code and the token is still valid, we can continue.

Of course, if the user did enter a code we have to check if the code they entered is correct. 

To do so, drag in another, final, condition. Before we can check if everything is as it should be, we have to add a variable.

6. Create a new object called WebUser that uses the WebUser model, and set the filter rule to ‘email_address’ equals ‘current_temporary_webuser.email’

Finally we can check if the entered code was correct.

7. Check if ‘is_sandbox’ is true, then add another rule that checks if the text_code equals sandbox code. Add another group, set it to or, then in the new group, set up the rule that text_code equals token.token. 

If they aren’t the same, raise an error saying the entered code was wrong, if they are the same, we can go to the final step of this action.

If the user enters the correct code we can finally drag in the authenticate user step.

In this step, we use the normal WebUser as an authentication profile. For the record ID, use ‘webuser.id’ and set the result of the step to the ‘jwt’ action variable.

8. After that, use a Delete Many Records step to delete all the tokens belonging to the user. Do this using ‘token.web_user.tokens’ in the collection option. 

Don’t forget to set the ‘jwt’ variable as the output variable in your Finish step! Otherwise, you will not be able to login and get redirected to the desired page.

If you’ve followed along and everything went correctly, your action should look like this.

By following this guide, you've created a more secure login for your application. Thoroughly test your implementation before deploying. This added security layer will increase user trust and protect sensitive data.