1
1
.
.
1
1
0
0
.
.
3
3
S
S
t
t
e
e
p
p
3
3
:
:
E
E
n
n
t
t
e
e
r
r
C
C
o
o
d
d
e
e
I
I
n
n
f
f
o
o
[
[
G
G
]
]
This tutorial shows how to
create Endpoint /EnterCode which displays HTML Page EnterCode.html where User can enter Google Temporary Code
which then calls Endpoint /VerifyCode which, if Code is valid, sets account.google2faAuthenticated = true inside DB
Application Schema [Results]
SecurityConfig
AccountService
AccountLoader
AccountRepository
http://localhost:8080/Configure
Tomcat
configure()
Browser
MyController
Configure.html
Account
EnterCode.html
SecurityBeans
P
P
r
r
o
o
c
c
e
e
d
d
u
u
r
r
e
e
Edit Class: MyController.java (add Endpoints: EnterCode, VerifyCode)
Edit File: Configure.html (add Button to go to EnterCode.html after configuration is over)
Create File: EnterCode.html (for User to enter Temporary Code)
MyController.java
package com.ivoronline.springboot_security_2fa.controllers;
import com.ivoronline.springboot_security_2fa.entities.Account;
import com.ivoronline.springboot_security_2fa.repositories.AccountRepository;
import com.warrenstrange.googleauth.GoogleAuthenticator;
import com.warrenstrange.googleauth.GoogleAuthenticatorKey;
import com.warrenstrange.googleauth.GoogleAuthenticatorQRGenerator;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequiredArgsConstructor
public class MyController {
private final AccountRepository accountRepository;
private final GoogleAuthenticator googleAuthenticator;
//======================================================================
// CONFIGURE (SERVICE & MOBILE APP)
//======================================================================
@RequestMapping("/Configure")
public String configure(Model model){
//GET USERNAME
User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String username = user.getUsername();
//CREATES NEW KEY IN DB (everytime it is called)
GoogleAuthenticatorKey key = googleAuthenticator.createCredentials(username);
//CONSTRUCT URL FOR QRCODE IMAGE
String googleURL = GoogleAuthenticatorQRGenerator.getOtpAuthURL("something", username, key);
//ADD GOOGLE URL AS INPUT PARAMETER TO HTML PAGE
model.addAttribute("googleURL", googleURL);
//RETURN CONFIRMATION HTML PAGE
return "Configure";
}
//======================================================================
// ENTER CODE
//======================================================================
@RequestMapping("/EnterCode")
public String enterCode(){
return "EnterCode";
}
//======================================================================
// VERIFY CODE
//======================================================================
@ResponseBody
@RequestMapping("/VerifyCode")
public String verifyCode(@RequestParam Integer code){
//VERIFY CODE
User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String username = user.getUsername();
Boolean validCode = googleAuthenticator.authorizeUser(username, code);
//RETURN IF CODE IS INVALID
if (!validCode) { return "Code is Invalid"; }
//UPDATE ACCOUNT
Account account = accountRepository.findByUsername(user.getUsername());
account.google2faAuthenticated = true;
accountRepository.save(account);
//RETURN MESSAGE TO USER
return "Code is Valid";
}
//======================================================================
// Hello
//======================================================================
@ResponseBody
@RequestMapping("/hello")
public String sayHello() {
return "Hello from Controller";
}
}
Configure.html
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<p> <img th:src="${googleURL}"/> </p>
<form method="GET" action="EnterCode">
<p> <input type="submit" name="submit" value="Enter Temporary Code"/> </p>
</form>
EnterCode.html
<form method="GET" action="VerifyCode">
<p> <input type="number" name="code" placeholder="Enter Temporary Code"/> </p>
<p> <input type="submit" name="submit"/> </p>
</form>