Multi-factor authentication in Go using Twilio Verify API
Time to read: 9 minutes
Multi-factor Authentication in Go using Twilio Verify API
As web applications become increasingly complex and security-critical, implementing robust authentication mechanisms is paramount. An excellent mechanism is Multi-factor authentication (MFA) adds an extra layer of security beyond traditional password-based systems.
Multi-factor authentication in Go applications enhances their security by requiring users to provide multiple forms of identification before gaining access. This approach significantly reduces the risk of unauthorized access, even if a user's password is compromised.
In this article, we'll explore how to implement MFA in a Go fullstack application using the Twilio Verify API and integrate it with a Vue.js frontend.
Prerequisites
Here are some requirements you need to follow in this tutorial:
- Go 1.22 or above installed on your system
- The Twilio Authy app installed on your phone
- A free Twilio account (free or paid). Click here to sign up if you don't already have an account.
- Ngrok, and make sure it’s authenticated
- Basic knowledge of Vue.js
- Familiarity with RESTful API concepts
Understanding multi-factor authentication with Twilio Verify
Twilio Verify is a powerful API that enables developers to add various forms of authentication to their applications. It supports SMS, voice, email, and push notifications for verification purposes. In our Go application, we'll focus on SMS verification and Time-based One-Time Passwords (TOTP) using Authy.
The architecture
Our MFA system consists of several key components:
- User Registration: Collects user information and initiates the MFA setup process
- Login: Handles initial authentication with username and password
- SMS Verification: Sends and verifies one-time codes via SMS
- TOTP Setup: Configures Time-based One-Time Password using Authy
Key components
- Go Backend: Handles API requests, interacts with Twilio Verify, and manages user authentication
- Vue.js Frontend: Provides the user interface for registration, login, and MFA processes
- Twilio Verify API: Manages SMS sending and verification
- Authy: Handles TOTP generation and verification
Benefits of MFA in Go applications
Multi-factor authentication (MFA) in Go applications offers several key advantages. These benefits enhance both the security posture of the application and the overall user experience. Let's explore the main advantages of this approach:
- Enhanced security through multiple authentication factors: By combining password-based authentication with SMS verification and TOTP, the application creates multiple layers of security, significantly reducing the risk of unauthorized access.
- Improved user trust and confidence: Implementing MFA demonstrates a commitment to security, enhancing user trust in the application and potentially increasing user adoption and retention rates.
- Compliance with industry standards: Many regulatory frameworks and industry standards require or strongly recommend MFA, making its implementation crucial for applications handling sensitive data or operating in regulated industries.
- Mitigation of common attack vectors: MFA effectively counters various attack methods such as phishing, credential stuffing, and brute force attacks, providing a robust defense against common security threats.
- Scalability and performance: Go's concurrent processing capabilities allow for efficient handling of MFA requests, ensuring the authentication process remains fast and responsive even as user numbers grow.
Use case with Twilio Verify API
In our demo, we'll build a fullstack application that implements a secure login process with the following steps:
- User registers an account
- User logs in with an email and password
- Server sends SMS OTP via Twilio Verify
- User verifies SMS OTP
- User sets up TOTP with Authy
- For subsequent logins, the user provides SMS and TOTP code after password
Retrieve your Twilio credentials
Login into your Twilio Console using your account details. From the toolbar's click Account > Account Management. Then, in the left-hand side navigation menu, under Keys & Credentials select API keys & tokens.
Take note of the test credentials as shown in the photo below, which include the Account SID and Auth Token, we will use them later in your application.
After getting your authentication tokens, you will create a Verify service from the dashboard. Click on Explore Products from the toolbar’s menu, click Verify, select Services, and click on the Create button to create one.
You will see a screen like the one below. Fill in your service name, select the channels, and add some descriptive notes for the service. For this tutorial, select all the verification channels.
After that, click on Continue and select Yes for the Enable Free Guard section.
At this point, your service is created and you will be redirected to a screen like the one below to update any settings and save them. For this tutorial, you do not have to update any of the settings. Just save the settings and your setup is ready.
Finally, take note of the Service SID as you will need it in your project to use this Verify service. You will find it in the next interface after saving the settings .
Create the Go API
In this section we will be creating the backend APIs that are needed for the end to end Multi-factor authentication. You will clone this starter repository which will help us add structure to our application, then install the necessary packages using the commands below:
First, clone the project and change into the new project directory with the following commands.
Then, install the required packages with the following command.
After successful installation of the packages, create a .env file and copy the key values from the .env.example file in the starter repository you cloned. Add the values for these keys and secrets as gotten from your Twilio console following the setup done initially.
In our project structure, we have the cmd, internals, and static directory. The cmd directory holds the entry file main.go, the internals have subdirectories including handlers, models, store and twilio respectively where our logic lives. The static directory has the static files for the Vue.js frontend.
We will start creating the logic for our APIs by updating the files in our model, store, twilio and handlers directory. In the verify.go file inside the internal/ twilio directory, update the code with the version below:
This file holds the functions for sending SMS OTP, verifying the SMS OTP, creating a TOTP URL or code, verifying the TOTP and subsequently creating a TOTP challenge for use after first verification. It uses Twilio's Go Helper Library to simplify calling the respective API endpoints. As seen, they accept parameters from the handlers and return the respective results back to the handlers.
Next, we will create the handlers logic. In the internal/handlers directory, first, update auth.go with the code below.
The logic here uses the in-memory module form internal/store/inmemory.go to interact with the app memory to create users and store them in the app memory. This module uses sync, a Go standard library package for this operation.
The logic also handles login by using the bcrypt library to check the hashed password and original password to match. It also implements the logout function which removes the authentication status for the user so that they will have to authenticate upon logging in again.
Next, update internal/handlers/user.go to match the code below.
Here, the user handler logic implements a GetUserInfo()
function for getting the user’s information from the in-memory store and returning the necessary details. It accepts an email address from the request’s query parameters and checks it against the memory store to get the matched user details.
Thirdly, update internal/handlers/verify.go to match the code below.
VerifyHandler
implements the five key logic functions for our Multi-factor authentication code. It uses the store
and twilio
variables to make calls to the Twilio API and the in-memory store respectively to create verifications and store the corresponding results.
- The
SendSMSOTP()
function uses the email from the request body to find the associated user’s phone number and sends an SMS OTP to the user. - The
VerifySMSOTP()
function also uses the email and code from the request body to confirm and update users, and verify the code using Twilio respectively - The
CreateTOTPFactor()
function creates the TOTP factor using the user ID as identity and user name as the friendly name of the TOTP in the Authy mobile app - The
VerifyFactor()
function uses the code and email from the request body to verify the TOTP factor created and also to update the user's details - The
CreateTOTPChallenge()
function uses the code from the request body to always verify the user subsequently. The codes are generated every 30 seconds in the Authy mobile app.
Finally for the APIs, update our entry file, main.go, in the cmd directory to reflect the logic in our handlers with the code below:
The main.go file uses the GoDotEnv package to load the environment variables from .env into the app, initializes the store
and twilio
instances and uses the gorilla/mux package to define routes in our application. The routes package is also used to serve static files in our app so we can access our user interface in the same server as well as our APIs.
Add the user interface for the multi factor authentication with Vue.js
Now that we are done with the backend service, we will be adding the user interface that our application will be using. If you are using the starter repository, the basic Vue components our application needs are already in place. But, we still need to create an entry file and the router file that Vue will use to render the components.
So, in the static directory, add this code to the index.html file:
The HTML file linked with all the packages we will need in the head tag namely: Tailwind CSS, Vue.js, Vue Router, A xios and qrcode-generator. The body is a div calling the Vue app with the id as “app” and then the router view for navigation between the components. The script section includes all the JavaScript components we have from the starter project.
After this, we will add the router and initialize the Vue app. We will update two files in the static folder here. The first is the router.js and then the app.js all in the js subdirectory.
First, update static/js/router.js to match the code below.
Then, update static/js/app.js to match the code below.
The router.js and the app.js file defines the routes for our application using Vue Router, and initializes the app instance by defining the routes and components it will use.
Test that the application works
Our application is now ready for testing. We want to mock a production environment, so we will use ngrok to proxy our local development environment to a live URL. First, start the application with the following command:
When the app has started successfully, in a new terminal tab or session, start ngrok to create a secure tunnel between the application and the public internet with the following command.
Now, open the ngrok generated Forwarding URL to see the application interface.
The app starts with the signup page. Add a name, email address, password, and an active phone number for the SMS verification.
When the signup is completed, you will be redirected to the login page as shown below to sign into the app. Log in to the application, which will trigger the Multi-factor authentication request.
After logging in, complete the first verification step, SMS verification. Successfully doing so will trigger the OTP service to send you the OTP via SMS. Input the OTP and proceed as shown below:
The next screen after successful OTP verification is the Twilio Authy app setup, one where you will scan the QR code with the app and the time-based one time passwords will start generating. Input any of the generated passwords to verify.
After a successful verification, you will now be able to access the app’s dashboard, which ends the flow for our Multi-factor authentication demo.
Below is also a video demonstration of how the Multi-factor authentication works end-to-end using Go, Vue.js and Twilio Verify.
That's how to implement Multi-factor authentication in Go using Twilio Verify
In this tutorial, we've explored the implementation of Multi-factor authentication in a Go application using the Twilio Verify API. We've walked through the process of building a robust authentication system, from user registration to TOTP setup, integrating both backend and frontend components seamlessly.
Our implementation demonstrates the power of combining Go's efficiency with Vue.js's reactive frontend, creating a secure and responsive user experience. The use of Twilio's Verify API showcases how modern applications can leverage third-party services to implement complex security features without reinventing the wheel.
As you apply these concepts to your own applications, remember that security is an ongoing process. Stay informed about the latest security best practices, regularly update your dependencies, and consider implementing additional security measures such as rate limiting and secure session management.
To deepen your understanding and stay up-to-date with the latest developments, refer to these resources:
- The Twilio Verify API Documentation
- Go's Documentation
- Vue.js's Documentation
- The application's source code
Desmond Obisi is a software engineer and a technical writer who loves developer experience engineering. He’s very invested in building products and providing the best experience to users through documentation, guides, building relations, and strategies around products. He can be reached on Twitter, LinkedIn, or at desmond.obisi.g20@gmail.com.
Related Posts
Related Resources
Twilio Docs
From APIs to SDKs to sample apps
API reference documentation, SDKs, helper libraries, quickstarts, and tutorials for your language and platform.
Resource Center
The latest ebooks, industry reports, and webinars
Learn from customer engagement experts to improve your own communication.
Ahoy
Twilio's developer community hub
Best practices, code samples, and inspiration to build communications and digital engagement experiences.