Introduction
In an era of increasing online security concerns, implementing robust authentication mechanisms is crucial. Two-Factor Authentication (2FA) provides an additional layer of security by requiring users to provide a second form of verification, typically a time-based one-time password (TOTP) or a HMAC-based one-time password (HOTP). In this blog post, we will explore how TOTP work and walk you through implementing 2FA using Golang.
TOTP (Time-Based One-Time Password)
Think of TOTP as a time-limited password that keeps changing every few seconds. When you set up 2FA on an application, it generates a secret key that is securely shared between the application and your device. Your device uses this key, combined with the current time, to generate a unique password that remains valid for a short period, typically 30 seconds. This password is entered along with your regular username and password to complete the login process. Popular applications like Google Authenticator use TOTP.
Implementing 2FA with TOTP in Golang:
To implement 2FA with TOTP in Golang, we will use the github.com/xlzd/gotp
library, which simplifies the process. Let's break down the steps:
Generating a new TOTP key
When you enable 2FA on an application, it generates a secret key. This key is shared securely between the application and your device.Generating a TOTP code:
To generate a TOTP code, your device combines the shared key with the current time and generates a unique password. This password remains valid for a short period, usually 30 seconds.Validating a TOTP code:
When you log in using 2FA, the application expects you to enter the correct TOTP code. The server uses the same shared key and checks if the code you provided matches the one generated on your device. If they match, you are granted access.
To better understand the process, let's go through a practical example with Golang
package main
import (
"fmt"
"time"
"github.com/skip2/go-qrcode"
"github.com/xlzd/gotp"
)
func main() {
randomSecret := gotp.RandomSecret(16)
fmt.Println("Random secret:", randomSecret)
generateTOTPWithSecret(randomSecret)
testOTPVerify(randomSecret)
}
func generateTOTPWithSecret(randomSecret string) {
totp := gotp.NewDefaultTOTP(randomSecret)
fmt.Println("current one-time password is:", totp.Now())
uri := totp.ProvisioningUri("user@email.com", "myApp")
fmt.Println(uri)
qrcode.WriteFile(uri, qrcode.Medium, 256, "qr.png")
}
func testOTPVerify(randomSecret string) {
totp := gotp.NewDefaultTOTP(randomSecret)
otpValue := totp.Now()
fmt.Println("current one-time password is:", otpValue)
ok := totp.Verify(otpValue, time.Now().Unix())
fmt.Println("verify OTP success:", ok)
}
In the above code, we first generate a random secret key using the gotp.RandomSecret
function. Then, we demonstrate how to generate a TOTP and display it, along with the QR code provisioning URI. The provisioning URI can be scanned by a mobile authenticator app (e.g., Google Authenticator) to set up the 2FA.
The testOTPVerify
function shows how to verify the TOTP with the current time.
By running this code, you'll experience the dynamic TOTP generation, which changes every few seconds, providing an extra layer of security for your application.
Conclusion
Implementing Two-Factor Authentication (2FA) adds an extra layer of security to your applications. In this blog post, we explored how TOTP work and provided non-technical explanations to help you understand the concepts. We also provided example code and walked you through implementing 2FA using Golang, using the github.com/xlzd/gotp
library.
Top comments (0)