Multi Factor Authentication with Spring Boot
- Performance and Security
Multi Factor Authentication with Spring Boot
1. Introduction to Multi Factor Authentication
In today’s world of cyber threats, security is paramount. Moreover, passwords alone are no longer enough to protect sensitive information. Multi factor authentication is a powerful security measure that adds an additional layer of protection to your applications.
Multi factor authentication is a security process that requires the user to provide two or more forms of authentication to access their accounts. The most common types of MFA include:
- Time-based One Time Password (TOTP)
- Push notifications via SMS or email
- Hardware tokens such as smart card
In this blog we will use TOTP (Time-based One Time Password) as the second form of identification. An app on the user’s mobile device, like Google Authenticator or Microsoft Authenticator, generates this TOTP.
2. How Multi Factor Authentication works
Here’s the user flow for Two-Factor Authentication:
- User enters their username and password: When a user tries to access a system or application that requires MFA, they will typically first enter their username and password, just as they would with a traditional login process.
- After entering their credentials, the MFA system prompts the user to provide additional forms of authentication. Depending on the MFA implementation, the system could send a one-time code to the user’s mobile device, require a bio-metric scan, or request a hardware token such as a smart card.
- User provides additional verification: The user then provides the requested form of authentication, such as entering the one-time code or scanning their fingerprint.
- MFA system verifies identity: The MFA system then verifies the user’s identity by checking the entered information against previously stored information.
- If the MFA system verifies the user’s identity, the system or application grants access.
3. How to implement MFA (TOTP) in spring boot
When the user enables two-factor authentication, the system generates a secret key and sends it to the user in the form of a QR code. The user can then scan the QR code using the authenticator app.
- Dependencies required
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<dependency> <groupId>dev.samstevens.totp</groupId> <artifactId>totp</artifactId> <version>1.7</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.0</version> </dependency> |
- User Registration flow
In this flow the user can opt whether they want to enable MFA or not while registering. To implement this we have added two fields to the “User” entity, i.e.
1 2 3 4 5 |
public class User { // other required fields for user info private boolean mfa; private String secret; } |
Depending on the user’s input we will update the “mfa” flag. If they enables it we will provide them with QR code. A secret is generated for user when they are registered. This secret is used to generate the QR code if user enables MFA.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
public String getUriForImage(String secret) { QrData data = new QrData.Builder() .label("Two-factor-auth-test") .secret(secret) .issuer("exampleTwoFactor") .algorithm(HashingAlgorithm.SHA1) .digits(6) .period(30) .build(); QrGenerator generator = new ZxingPngQrGenerator(); byte[] imageData = new byte[0]; try { imageData = generator.generate(data); } catch (QrGenerationException e) { log.error("unable to generate QrCode"); } String mimeType = generator.getImageMimeType(); return getDataUriForImage(imageData, mimeType); } |
While sending response after registration we are also sending mfa flag and the QR code image URI. On the front-end side we check if the flag is enabled or not. If true we redirect to the URI.
They can scan the QR using Google Authenticator to generate an OTP.
Note:- If mfa is not enabled the flow works as simple JWT(username, password) authentication.
- Login and Verify flow
In this flow we first ask user for username and password. After that we check if mfa is enable if yes we redirect to “/verify” to verify the OTP generated in the authenticator app.
1 2 3 4 5 6 7 8 9 10 11 |
public String loginUser(String username, String password) { Authentication authentication = authenticationManager .authenticate(new UsernamePasswordAuthenticationToken(username, password)); User user = userRepository.findByUsername(username).get(); if(user.isMfa()) { return ""; // no token generated as mfa is enabled } return jwtTokenManager.generateToken(authentication); } |
After entering the OTP the code is then verified. If passes an access token is generated else an exception is thrown for incorrect code.
1 2 3 4 5 6 |
public boolean verifyCode(String code, String secret) { TimeProvider timeProvider = new SystemTimeProvider(); CodeGenerator codeGenerator = new DefaultCodeGenerator(); CodeVerifier verifier = new DefaultCodeVerifier(codeGenerator, timeProvider); return verifier.isValidCode(secret, code); } |
if the code is verified the user is granted access to resources and is redirected forward.
4. Pros of using Multi Factor Authentication
- Improved security: MFA provides an additional layer of security that makes it more difficult for attackers to gain access to a user’s account, even if they have obtained the user’s password.
- Mitigates password-related risks: Since passwords can be weak and easily compromised, MFA reduces the risk of a password-based attack, such as brute force or dictionary attacks.
- Versatility: An organisation or application can implement MFA in various forms, such as bio-metric, OTP, smart cards, etc., and can tailor it to suit their specific needs.
5. Cons of using Multi Factor Authentication
- Complexity: MFA can add complexity to the authentication process, which may result in increased user friction and a higher likelihood of user errors.
- Cost: Implementing MFA can be costly, especially when using hardware tokens or biometric scanners.
- Maintenance: MFA requires regular maintenance and updates, which can be time-consuming and costly.
- False sense of security: MFA can give users a false sense of security, leading them to neglect other security best practices such as keeping their passwords strong and up-to-date.
6. When to use MFA and it’s use-cases
In general, one should use MFA in any scenario where the risks associated with unauthorised access are high, such as accessing sensitive data or conducting financial transactions. MFA can greatly reduce the risk of data breaches, cyber attacks, and other security incidents, making it an important tool for protecting both individuals and organisations.
Here are some common use cases for MFA:
- Financial transactions: Online banking and financial transactions commonly use MFA to prevent unauthorised access to sensitive financial data.
- Healthcare data: MFA can secure access to electronic health records (EHRs) and other sensitive healthcare data.
- E-commerce: Online shopping platforms can use MFA to secure their systems and prevent unauthorised access to sensitive customer information and financial data.
7. Conclusion
Implementing MFA in Spring Boot is an important security measure that can provide an extra layer of protection to user accounts and systems. By requiring users to provide two or more forms of authentication, MFA can help prevent unauthorised access and mitigate the risk of data breaches. However, it is important to carefully consider the implementation of MFA, taking into account the specific needs of the application and its users.
8. References
- https://medium.com/@vlad.milytin/google-authenticator-in-java-spring-e7e40e5b9a86
- https://sultanov.dev/blog/multi-factor-authentication-with-spring-boot-and-oauth2/
- https://www.youtube.com/watch?v=km1k63hyHgE&pp=ygUqbXVsdGkgZmFjdG9yIGF1dGhlbnRpY2F0aW9uIGluIHNwcmluZyBib290
9. Further Readings
You can also go through the blogs below for know more about JWT authentication and Google APIs.
- JWT in Spring Boot – https://www.aurigait.com/blog/jwt-spring-boot/
- Accessing Google Calendar data – https://www.aurigait.com/blog/accessing-google-calendar-data-using-google-calendar-api/
- Implement Method Level Security – https://www.aurigait.com/blog/method-level-security/
- Read Encrypted Attachments using Gmail API? – https://www.aurigait.com/blog/how-to-read-encrypted-attachments-using-gmail-api/
Related content
Auriga: Leveling Up for Enterprise Growth!
Auriga’s journey began in 2010 crafting products for India’s