A Time-Based One-Time Password (TOTP) is a two-factor authentication (2FA) method that generates a password that is valid only for a short period, typically 30 seconds. It is commonly used in conjunction with other forms of authentication, such as a username and password, to provide an extra layer of security.
How does TOTP work?
-
Shared Secret Key: The user and the authentication server share a secret key (often generated during account setup). This key is stored securely on both the client (e.g., in a mobile app like Google Authenticator or Authy) and the server.
-
Current Time: TOTP relies on the current time (usually in UTC) and divides it into time intervals (e.g., 30 seconds). Each time interval has a unique number, which is used in the OTP generation process.
-
OTP Generation
-
OTP Validity: The OTP is only valid for a short period (usually 30 seconds). Once the time expires, the code becomes invalid, and a new code is generated.
-
Authentication
-
The user enters the OTP shown in their authentication app.
-
The server also calculates the OTP based on the shared secret key and the current time.
-
If the OTP entered by the user matches the one calculated by the server (within a certain tolerance window), authentication is successful.
-
Syncing: Both the client and server must be synchronized at the same time. If there is a significant time drift between them, the OTP may not match, leading to authentication failure.
Flowchart
I have represented each step in the flowchart below.
![Flowchart]()
Implementation
Let's Try To understand the implementation with C#.
There are 2 ways to implement the TOTP logic (Generate a Sharable Key and validate the TOTP).
- Create your Custom Logic
OR
- Use existing Libraries
Since our main goal here is to enable TOTP for Application, I will be using the existing Open-source Library.
Otp.net
I am using Otp.net to implement the functionality. Let's see step by step approach.
Reference Otp.net
Add the Otp.net package to the project
dotnet add package Otp.NET
Generate Secret
As the initial step in implementation, generate the Secret Key, which will be used to create and validate the OTP.
using OtpNet;
.
.
.
byte[] secretKey = KeyGeneration.GenerateRandomKey(20); // 20 bytes = 160 bits
string base32Secret = Base32Encoding.ToString(secretKey);
Console.WriteLine("Secret Key (Base32): " + base32Secret);
Convert Secret to QR code for Authenticator Apps
As we need a QR code of the above generated Secret to register on the Authenticator app, use an online resource to convert a secret into a QR code.
Now register it on Google authenticator
Validate OTP
Here is the code to validate the OTP
// Verify OTP (returns true if valid in the allowed window)
var isValid = totp.VerifyTotp(otp, out long timeStepMatched);
Console.WriteLine("Is OTP Valid? " + isValid);
Note. We should store the secret in the Database against the User to send it for validation.