We typically protect our applications using an identifier (such as a username or email address), and a password. Most organisations have also started to use 2-Factor Authentication (2FA), where apart from a password, you will need to identify yourself through a 2nd medium (such as a password on your phone).
I will demonstrate how you can implement a One Time Password (OTP) based setup which you can use as a 2FA or a standalone setup.
The concept is quite easy to understand:
- We will use TOTP (Time based OTP)
- Create a Hex Value which will be a user’s key (such as a1b2c3d4e5)
- Generate a Base32 encoded version of the key
- Install an app FreeOTP in your phone and specify the total OTP digits (6 by default), and the step size in seconds (30 seconds)
- Feed in the user’s key, and the Base32 encoded version along with other identifiers such as email address for identification
- Now, whenever you use the FreeOTP, you will receive a number valid for 30 seconds (the step size / interval)
- Validate the number on the server through
oathtoolby specifying the digits, the step size, and the Hex Value. It will match.
Let’s get started.
oathtool on the server which will do the validation
apt-get install oathtool
Install FreeOTP on your mobile phone. It is a free app available on iOS and Android.
Create a Hex Key
The easiest way is
head -10 /dev/urandom | md5sum | cut -b 1-8
The above command will output an 8-digit Hex Value.
You can create more complicated keys through
head -10 /dev/urandom | md5sum | cut -b 1-30
You can also use a combination of 0-9 digits and a-f alphabets to create the key.
Get a base32 encoded version of the Hex Value
Run the following command
oathtool --totp --verbose YOUR_HEX_KEY
You will see among other items, a “Base32 secret“. Note that value as you will need it to feed into FreeOTP.
- Enter the Issuer – it is for your reference. Can be an email or anything else.
- Enter the Hex Value as ID
- Enter the Base32 Value as Secret
- Interval is 30 Seconds by default
- Digits are 6 by default
- Algorithm is SHA1 by default
That’s all. Now save that information, and when you click on your entry, it will show you a number valid for 30 seconds.
Validate it on the server
Use the command
oathtool to validate it on the server
oathtool --totp YOUR_HEX_KEY
The above assumes that you’ve taken the step size (interval) as 30 and digits as 6. If you have done a different configuration, you can try out the following too by specifying the step size and digits explicitly.
oathtool --totp -s 30 -d 6 YOUR_HEX_KEY
(Replace 30 & 6 with your step size & digits respectively)
- To manage users, you can integrate it with a user database where each user also has a randomly generated key associated with it. Create a QR code with all relevant information (Issuer, ID, Secret) so that FreeOTP can easily read it. Give it to the users to add information to their phones.
- At the server end, when you are authenticating a user, ask for a identifier (such as the email address or a username), and use the key associated with that identifier to generate an OTP using the
oathtoolcommand. If the one provided by the user matches with the one generated by your system, then you can authenticate the user.
- What if 30 seconds is too less and while the user is entering the information, the information changes? You can generate future OTPs by using the time window parameter (-w). You can also use a historical time using the current time parameter (-n). For example:
oathtool --totp -w 5 -N "2017-08-16 22:46:00" 1a2b3c4d5e
I’m trying to use freeOTP as 2FA app for authentication of instagram but i can’t do it.
Help me please
This does not work. The screen shot of FreeOTP is different from what I installed on Android today. Also I did not see any field while entering the data in FreeOTP called “ID” Possibly the algorithm has changed. Also, I noticed that you used MD5SUM when generating the key but later on you indicate that the algorithm is SHA1 — I am confused, and possibly do not know what is going on. Would appreciate clarity with the new version of FreeOTP
Thanks for the effort taken though
I found out the correct method. This is what I did on an Ubuntu server
I installed this bash script https://raw.githubusercontent.com/mcepl/gen-oath-safe/master/gen-oath-safe
I saved that file on my server as gen-oath-safe.sh and gave it the executable permission (chmod +x gen-oath-safe.sh )
That script also looks for a qrcode generator and a way to convert the image generated from it to ascii (so that I can scan it) But dont worry about that… It still does the work
I ran this:
./gen-oath-safe.sh exampleuser totp
You get output of this nature
Key in Hex: 67246b5611e7915152fb9598a1602db3b49b38c8
Key in b32: M4SGWVQR46IVCUX3SWMKCYBNWO2JWOGI (checksum: 7)
(Then some errors as the Qrcode generator, and img2text is not available)
You can use this tool to conver the URI into a qrcode here
In the above site; you can go to the input field above the qrcode image and copy and paste the URI: otpauth://…. generated above
That can be scanned by FreeOTP and to verify the user run the command
oathtool –totp 67246b5611e7915152fb9598a1602db3b49b38c8
Hope this helps someone