Extra Layer of Security? Let's Explore 2FA with Go
Multi-factor authentication is an electronic authentication method in which a user is granted access to a website or application only after successfully presenting two or more pieces of evidence to an authentication mechanism: knowledge, possession, and inherence.
Source: Wikipedia
Implementation in Golang
To verify a specific user/device we need to assign it a unique secret key
.
Convert that secret key
to base 32 encoding and build an otpauth://
URL.
// converting secret key to base32 encoding
secretBase32 := base32.StdEncoding.EncodeToString(secretKey)
issuer := "datumbrain.com"
account := "user4"
// creating otpauth url
authUrl := fmt.Sprintf("otpauth://totp/%s:%s?secret=%s&issuer=%s",
url.PathEscape(issuer), url.PathEscape(account), secretBase32, issuer)
issuer
in the above URL represents your application.account
represents the user in your application, it can be the user’s email, username, etc.
You can generate a QR code from this URL to scan with some mobile application like Google Authenticator
.
QR Code
You can use some package like rsc.io/qr
to generate a QR code from the above URL to scan with a mobile TOTP
application.
// encoding url to qr code
qrCode, err := qr.Encode(authUrl, qr.Q)
if err != nil {
panic(err)
}
// writing qr code to png file `/tmp/qr.png`
err = ioutil.WriteFile("/tmp/qr.png", qrCode.PNG(), 0600)
if err != nil {
panic(err)
}
Authentication
Now when the user has configured their TOTP client and got their one-time password, you will need to verify it.
For this, there is a golang package github.com/dgryski/dgoogauth
available on GitHub which may help you.
client := &dgoogauth.OTPConfig {
Secret: secretBase32,
}
isVerified, err := client.Authenticate(usersOtp)
The Authenticate()
method will return an error when the OTP doesn’t have the correct format. It returns true
if the OTP is correct or false
otherwise.
Tell us what you think in comments below.