I'm trying to create a more secure way to reset a forgotten password with Java web and HSQLDB without any framework.
I created a form where the user can insert his email and if the email is in database, it will automatically send an email with a link for password reset. This link has a specific token that is created for each user when they click on the button for receiving the email. This token is inserted in the database and also the timestamp for when it is created.
I'm trying to delete the token from the database if it reached a limit time of 5 minutes but it doesn't work. Is there any way to do this? Thank you.
My table:
CREATE TABLE user (
id bigint identity NOT NULL,
username varchar(50) NOT NULL,
email varchar(50) NOT NULL,
password varchar(50) NOT NULL,
attempts int DEFAULT 3,
state varchar(50) DEFAULT 'Active’,
reset_token uuid,
time_token TIMESTAMP,
PRIMARY KEY (id)
);
The tokengenerator:
public class TokenGenerator {
public static String UniqueToken() {
String token = UUID.randomUUID().toString();
return token;
}}
My class ForgotPasswordHandler.java:
public class ForgotPasswordHandler {
private static PreparedStatement ps = null;
private static ResultSet rs = null;
private static Connection con = DBConnectionManager.getConnection();
//Creates a token for the user when it clicks on submit for forgot password
public static void CreateToken (String email) {
try
{
if (con == null){
System.out.println("Failed connection");
}else{
String token = TokenGenerator.UniqueToken();
PreparedStatement ps = con.prepareStatement(
"UPDATE user SET reset_token = ?, time_token = ? WHERE email = ?");
ps.setString(1,token);
ps.setTimestamp(2,new Timestamp(new Date().getTime()));
ps.setString(3, email);
ps.executeUpdate();
ps.close();
}}
catch (Exception e) {
e.printStackTrace(System.out);
}
}
//This is where I'm having trouble to delete the actual token after 5 minutes.
public static void DeleteToken() {
try
{
if (con == null){
System.out.println("Failed Connection");
}else{
PreparedStatement ps = con.prepareStatement(
"UPDATE user SET reset_token = NULL WHERE time_token < NOW() - INTERVAL 5 MINUTE");
ps.executeUpdate();
ps.close();
}}
catch (Exception e) {
e.printStackTrace(System.out);
}
}
}
My Servlet ForgotPassword.java:
public class ForgotPassword extends HttpServlet {
private static final long serialVersionUID = 1L;
private String host;
private String port;
private String email;
private String name;
private String pass;
public void init() {
// reads SMTP server setting from web.xml file
ServletContext context = getServletContext();
host = context.getInitParameter("host");
port = context.getInitParameter("port");
email = context.getInitParameter("email");
name = context.getInitParameter("name");
pass = context.getInitParameter("pass");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//verify if emails exists in db
String email = request.getParameter("email");
if(!UserReset.EmailCheck(email)) {
String message = "This email isn't in our database";
request.setAttribute("message", message);
request.getRequestDispatcher("reset.jsp").forward(request, response);
} else {
String recipient = request.getParameter("email");
String subject = "Your Password has been reset";
String token = TokenGenerator.UniqueToken();
ForgotPasswordHandler.CreateToken(email);
ForgotPasswordHandler.DeleteToken();
String url = "http://localhost:8080/login/reset-password.jsp?token=" + token;
UserReset.RefreshState(email);
//Builds email message and sends it
String content = "Hello, please change your password in this link:" + url;
content += "\nObrigado!";
String message = "";
try {
EmailSender.sendEmail(host, port, email, name, pass,
recipient, subject, content);
message = "Please verify your email.";
} catch (Exception ex) {
ex.printStackTrace();
message = "Ops, an error occured: " + ex.getMessage();
} finally {
request.setAttribute("message", message);
request.getRequestDispatcher("reset.jsp").forward(request, response);
}
}
}
}
You probably shouldn't be deleting the token actively. Just record the time the token was issued, and then when the new query comes in, get the create time and check that it is within 5 minutes.