Build a One-Time Password-Based Login System using Go and Twilio
Time to read: 5 minutes
Building a One-Time Password (OTP) Login System via Twilio and Go
In a world where data breaches are a constant threat, passwordless authentication methods like One-Time Passwords (OTPs) have become the go-to solution for secure logins. Pairing the simplicity of Go with the robust messaging power of Twilio, you can build a seamless OTP login system in no time.
If you're ready to boost your app's security while keeping things user-friendly? Let’s dive in.
Prerequisites
Before you begin, ensure you have the following:
- Go version 1.22 or above
- A Twilio account (either free or paid). If you are new to Twilio, click here to create a free account
- Access to a MySQL database
- Basic knowledge of Go
- A mobile phone that can send SMS
Create the Go application
Initialize a new Go module
To create the Go application, start by creating the Go project and initialising a go module, by running the following commands in your terminal:
Create the environment variables
To keep your API keys and other sensitive information out of code, you should use environment variables stored in a .env file. Now, create a .env file in the root of your project and add the following to it:
Then, update the DB_SOURCE
key to match your MySQL credentials. Check out the DSN format documentation, if you're unfamiliar with how the value is formatted.
Environment variables stored in the .env file contain sensitive information, such as Twilio credentials for authentication and messaging (TWILIO_ACCOUNT_SID
, TWILIO_AUTH_TOKEN
, and TWILIO_PHONE_NUMBER
). The file also holds the database connection string (DB_SOURCE
) used to access the user information database.
Retrieve your Twilio access credentials
Next, log in to your Twilio Console to retrieve your Account SID, Auth Token, and Twilio phone number, as you can see in the screenshot below.
Then, use them to replace <your_twilio_account_sid>
, <your_twilio_auth_token>
, and <your_twilio_phone_number>
, respectively, in .env.
Create the database schema
Now, you will create the application database to store the user details. To do that, login to your MySQL server, create a new database named "userinfo" and then run the query below to create a table named "reg_users".


The image above shows the structure of the reg_users table in the "userinfo" database. It lists the columns of the table, such as "ID", "Fullname", "Phone", and "Password", along with their data types. Essentially, it's a visual of how the "reg_users" table is set up.
Install the required dependencies
The application will use Twilio's official Helper Library for Go to send SMS, GoDotEnv to create environment variables from the variables defined in .env, and the Go MySQL Driver to interact with MySQL. To install them, run the command below:
Create the application's logic
The code below implements a user registration and login system with OTP verification by using a MySQL database to store user information, bcrypt for password hashing, and Twilio for sending OTPs via SMS. The application manages user sessions and provides pages for registration, login, OTP verification, and a success dashboard.
The Go code below should be placed in the main.go at the root of your project directory, and ensure that your MySQL database is running and has the required "reg_users" table before executing the program.
The Go code above is used to build a web-based authentication system that uses MySQL for user storage and Twilio for OTP-based login verification. It starts by loading environment variables and initializing a MySQL database connection. The database is accessed using the go-sql-driver/mysql package, and sessions are managed with gorilla/sessions.
The system serves multiple web pages through HTML templates, including registration, login, verification, and a success page after authentication. It has HTTP handlers for user registration, where passwords are hashed using bcrypt before storing them in the database. When a user logs in, their credentials are validated against the stored hash. Instead of direct login, the system generates a six-digit OTP, stores it temporarily with a five-minute expiration, and sends it to the user via Twilio's messaging API.
Upon receiving the OTP, the user submits it for verification. If the OTP is correct and within its expiration time, the session is marked as authenticated, and the user is redirected to a success page. Otherwise, they are prompted to try again or request a new OTP. The application runs an HTTP server listening on port 8080, using gorilla/mux for routing, handling both GET and POST requests for authentication flows.
The OTP generation relies on the crypto/rand package for security, and a mutex (sync.Mutex) is used to synchronize access to the OTP store and expiration maps. If Twilio is not configured, OTPs are logged to the console. Error handling is integrated throughout to provide user-friendly messages and prevent database-related issues. The app structure is modular, ensuring each function handles a specific responsibility in the authentication process.
Create the application's templates
Now, create the application template for the register, login, and verify pages. To do that, go to the application's root directory and create a folder named templates. To create the register template, create a file named register.html and add the following code to it.
To create the login page template, create a new login.html file in the templates directory, and add the following code to it.
Now, for the verify page, create a new file named verify.html in the templates directory, and add the following code to it.
Now, for the success page, create a new file named success.html in the templates directory, and add the following code to it.
Test the application
To test that the application works as expected. You have to start the application development server using the code below:
After starting the application, open http://localhost:8080/register in your preferred browser and register a new account, as shown in the image below.


After registration, you will be redirected to the login dashboard. Log in using your phone number and password as shown in the image below.


After the login is verified, you will receive an OTP to confirm your account login as shown in the screenshot below.


On the verification page, enter your OTP as shown in the screenshot below to verify your login. If your OTP is correct, a login successful message is displayed. Otherwise, the user is redirected back to the login page.


After you enter the OTP received and click on the verify button as shown above, it will then direct you to a success page as shown below.


That's how to build an OTP login system with Twilio and Go
You’ve successfully built an OTP login system using Go and Twilio, learning how to generate OTPs, send them via Twilio, and verify them through a simple API. The next steps include using a database like Redis instead of storing OTPs in memory, implementing rate limiting to prevent brute-force attacks, and deploying the application using ngrok or a cloud provider. 🚀
This implementation includes user registration with a password, user login with OTP verification, a MySQL database to store user credentials and OTPs, Twilio OTP integration, rate-limiting for OTP requests, and brute-force protection for OTP verification.
David Fagbuyiro is a software engineer and technical writer who is passionate about extending his knowledge to developers through technical writing. You can find him on LinkedIn.
OTP icon in the main image was created by Freepik on Flaticon.
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.