I am currently implementing the forget password logic in my Spring application. The process involves generating a token, sending it via email, and simultaneously setting a session attribute named "resetToken" with a custom class UserResetToken. However, when I attempt to retrieve this session attribute during the change password process, it consistently returns null. Here's the relevant code snippets:
Sending Email and Setting Session Attribute:
public void sendMail(String to,HttpServletRequest request) { HttpSession session = request.getSession(true); User user = userRepository.findByEmailIgnoreCase(to); if (user == null) { throw new NoSuchElementException("User with email " + to +" not found"); } String token = generateToken(to); Instant creationTime = Instant.now(); Instant expirationTime = creationTime.plusSeconds(220); UserResetToken userResetToken = new UserResetToken(to, token, creationTime, expirationTime); session.setAttribute("resetToken", userResetToken); String htmlContent; try { String templatePath = "Mypath/email.html"; htmlContent = new String(Files.readAllBytes(Paths.get(templatePath))); } catch (Exception e) { throw new RuntimeException("Failed to read HTML template", e); } String resetLink = "http://localhost:4200/changepassword?token=" + token; htmlContent = htmlContent.replace("{{resetLink}}", resetLink); try { MimeMessage mimeMessage = javaMailSender.createMimeMessage(); MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, true); mimeMessageHelper.setFrom(fromEmail); mimeMessageHelper.setTo(to); mimeMessageHelper.setSubject("Password Reset"); mimeMessageHelper.setText(htmlContent, true); javaMailSender.send(mimeMessage); } catch (Exception e) { throw new RuntimeException("Failed to send email", e); } } private String generateToken(String email) { SecretKey secretKey = SecretKeyGenerator.generateSecretKey(); long expirationMillis = System.currentTimeMillis() + (2 60 60 * 1000); Date expirationDate = new Date(expirationMillis); String token = Jwts.builder() .setSubject(email) .setExpiration(expirationDate) .signWith(SignatureAlgorithm.HS256, secretKey) .compact(); return token; } public boolean isTokenExpired(UserResetToken userResetToken) { Instant now = Instant.now(); Instant expirationTime = userResetToken.getExpirationTime(); return now.isAfter(expirationTime); }
Change Password Method:
@Overridepublic void changePassword(UserDto dto, HttpServletRequest request) { HttpSession session = request.getSession(); UserResetToken userResetToken = (UserResetToken) session.getAttribute("resetToken"); if (userResetToken == null || isTokenExpired(userResetToken)) { throw new RuntimeException("Password reset link has expired"); } User user = userRepository.findByUsernameIgnoreCaseOrEmailIgnoreCase(dto.getUsername(),dto.getEmail()); if (user == null) { throw new NoSuchElementException("User with username " + dto.getUsername() +" not found"); } if (dto.getPassword() != null && !passwordEncoder.matches(dto.getPassword(), user.getPassword())) { throw new IllegalArgumentException("Entered password does not match the current password"); } user.setPassword(passwordEncoder.encode(dto.getNewPassword())); user.setLastModifiedDatetime(new Date()); user.setLastModifiedBy(user.getUsername()); userRepository.save(user);}
UserResetToken Class:
package com.project.officeadministrationsystem.dto;import java.io.Serializable;import java.time.Instant;import lombok.AllArgsConstructor;import lombok.Data;import lombok.EqualsAndHashCode;import lombok.NoArgsConstructor;@Data@NoArgsConstructor@AllArgsConstructor@EqualsAndHashCode(callSuper = false, of = { "email" })public class UserResetToken implements Serializable { private static final long serialVersionUID = 1L; private String email; private String resetToken; private Instant creationTime; private Instant expirationTime;}
Additional Information:
The session is configured to store data in a JDBC database (table: spring_session_attributes) with a timeout of 3600 sec
`session: store-type: jdbc jdbc: initialize-schema: always timeout: seconds: 3600`
The UserResetToken class implements Serializable and has appropriate getters and setters
No exceptions or errors are thrown during the email sending process.The application is running on a local server (http://localhost:4200).
Question:
Why am I unable to retrieve the session attribute "resetToken" during the change password process? Is there any mistake in my implementation that could be causing this issue? Any insights or suggestions would be greatly appreciated. Thank you!