An OTP (One-Time Password) is a password valid for a single use. It is frequently employed to bolster security in different situations, including email verification, Two-Factor Authentication (2FA), transaction authorization, and verification of suspicious account activity.
There are at least three types of OTPs: normal OTP, HOTP (Hash-based OTP), and TOTP (Time-based OTP).
Initially, Peng Feng employed local cache to calculate normal OTP expiration time and validate whether the token has expired and become invalid.
Then, Richard utilized an OTP table to store the normal token and expiration time. Each time, the system checks if the OTP is valid against the table.
In a recent update, we transitioned from OTP to TOTP, making it ready for multifactor authentication, as this feature will be mandatory in the next stage.
Multifactor Authentication (MFA) introduces an additional layer of authentication beyond something you know, like a password, by incorporating something you have.
There are three methods for MFA:
- After logging in with a password, an OTP is sent via email for action verification (rare case).
- Sending an OTP via text message (common).
- Prompting the user to enter the OTP using an Authentication APP, such as Okta Authenticator or Google Authenticator.
TOTP is employed for MFA, and the algorithm in the provided code snippet (https://gist.github.com/rakeshopensource/def80fac825c3e65804e0d080d2fa9a7) is utilized, with the only modification being the expiration time set to 10 minutes (Richard’s strategy).
private static final int TIME_STEP = 600; // 10 minutes
In TOTP, every user associates with a secret key. Richard has developed a suite of random generator tools, including methods for generating random strings, numbers, and more. The secret key is a randomly generated string with a length of 10 characters.
Below, you’ll find the code for the random generator.
class MNRandomUtil {
...
public static String randomString(String baseString, int length) {
StringBuilder sb = new StringBuilder();
if (length < 1) {
length = 1;
}
int baseLength = baseString.length();
for(int i = 0; i < length; ++i) {
int number = getRandom().nextInt(baseLength);
sb.append(baseString.charAt(number));
}
return sb.toString();
}
public static String randomString(int length) {
return randomString("abcdefghijklmnopqrstuvwxyz0123456789", length);
}
...
}
And link it to the user, which will be invoked whenever a user is initiated.
class MNUser {
...
@Description("For TOTP")
private String secretKey = MNRandomUtil.randomString(10);
...
}