Implementing TOTP Using Google Authenticator in Java
Posted By : Ekesh Bahuguna | 29-Jun-2018
Google authenticator is used to
Dependencies: Add following maven
<!-- https://mvnrepository.com/artifact/com.warrenstrange/googleauth -->
<dependency>
<groupId>com.warrenstrange</groupId>
<artifactId>googleauth</artifactId>
<version>1.1.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.zxing/javase -->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.3.3</version>
</dependency>
Steps to implement Google Authenticator:
1- Generating google auth key
final GoogleAuthenticator gAuth = new GoogleAuthenticator();
final GoogleAuthenticatorKey googleAuthkey = gAuth.createCredentials();
String key = googleAuthkey.getKey();
2- Generating key URI
URI uri = new URI("otpauth", "totp", "/" + issuer + ":" + account, "secret=" + secret + "&issuer=" + issuer,null);
uri.toASCIIString();
3-
public Map<String, String> qrCodeGeneration(Users user) throws URISyntaxException, WriterException, IOException {
String key = getTwoFactorKey(user);
String filePath = qrCodeLocation + File.separator + user.getId() + ".png";
String charset = "UTF-8"; // or "ISO-8859-1"
Map<EncodeHintType, ErrorCorrectionLevel> hintMap = new EnumMap<>(EncodeHintType.class);
hintMap.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
String keyUri = generateKeyUri("test.com", user.getEmailId(), key);
String qrCodeData = keyUri;
String base64Image = createQRCode(qrCodeData, filePath, charset, hintMap, 200, 200);
Map<String, String> map = new HashMap<>();
map.put("fileName", user.getId() + ".png");
map.put("key", key);
map.put("base64Image", base64Image);
map.put("verificationToken", verificationToken.getToken());
return map;
}
//Configure the Google Authenticator App by scanning the following QR code image
private static String createQRCode(String qrCodeData, String filePath, String charset,
@SuppressWarnings("rawtypes") Map hintMap, int qrCodeheight, int qrCodewidth)
throws WriterException, IOException {
@SuppressWarnings("unchecked")
BitMatrix matrix = new MultiFormatWriter().encode(new String(qrCodeData.getBytes(charset), charset),
BarcodeFormat.QR_CODE, qrCodewidth, qrCodeheight, hintMap);
File file = new File(filePath);
MatrixToImageWriter.writeToPath(matrix, filePath.substring(filePath.lastIndexOf('.') + 1), file.toPath());
Encoder encoder = Base64.getEncoder();
String base64Image = encoder.encodeToString(Files.readAllBytes(file.toPath()));
// using PosixFilePermission to set file permissions 777
Set<PosixFilePermission> perms = new HashSet<>();
// add owners permission
perms.add(PosixFilePermission.OWNER_READ);
perms.add(PosixFilePermission.OWNER_WRITE);
// add group permissions
perms.add(PosixFilePermission.GROUP_READ);
perms.add(PosixFilePermission.GROUP_WRITE);
// add others permissions
perms.add(PosixFilePermission.OTHERS_READ);
Files.setPosixFilePermissions(Paths.get(file.toString()), perms);
logger.info("2FA QR code generated");
return "data:image/png;base64," + base64Image;
}
4- perform authentication
//To check whether generated google auth key is authenticated or not
public boolean performAuthentication(String value, Users user) {
Integer totp = Integer.valueOf((value.equals("") ? "-1" : value));
boolean unused = isUnusedPassword(totp, windowSize.get());
boolean matches = gAuth.authorize(user.getGoogle2FaAuthKey(), totp);
return (unused && matches);
}
private long KEY_VALIDATION_INTERVAL_MS = TimeUnit.SECONDS.toMillis(30);
private boolean isUnusedPassword(int password, int windowSize) {
long now = new Date().getTime();
long timeslotNow = now / KEY_VALIDATION_INTERVAL_MS;
int forwardTimeslots = ((windowSize - 1) / 2);
long timeslotThen = lastVerifiedTime / KEY_VALIDATION_INTERVAL_MS;
if (password != lastUsedPassword || timeslotNow > timeslotThen + forwardTimeslots) {
lastUsedPassword = password;
lastVerifiedTime = now;
return true;
}
return false;
}
Advantages:
Using google 2fa, if anyone knows username and password of the user that is not sufficient to break the security. The attacker also requires the secret key or the device on which google authenticator app is running.
Note:
In google authenticator,
Disadvantages:
If anyone gets access to your secret key then, they can generate their own valid codes. If service doesn't prevent the specific login attempt, hackers may still be able to compromise your account through brute force.
Cookies are important to the proper functioning of a site. To improve your experience, we use cookies to remember log-in details and provide secure log-in, collect statistics to optimize site functionality, and deliver content tailored to your interests. Click Agree and Proceed to accept cookies and go directly to the site or click on View Cookie Settings to see detailed descriptions of the types of cookies and choose whether to accept certain cookies while on the site.
About Author
Ekesh Bahuguna
Ekesh is Java Developer. Along with that he is good in linux, c, networking and competitive programming. He love to answer over Quora.