I’d googled about this problem but i still can’t find an answer for myself.
I’m using Spring Boot and what I’m doing is generating a link where users can access and change password. The link, containing a jwt token, will be sent to the user’s email
Here’s the function that i use to do that
public ResponseEntity<String> sendChangePasswordEmail(String email, boolean isInManagement) {
if(isExistEmail(email)) {
log.warn("Sent email to: " + email);
String token = jwtService.generateToken(email, 3600000); //generate token here
String link;
if(isInManagement) {
link = Constants.CONTEXT_PATH + "/management/changepassword?auth=" + token;
} else {
link = Constants.CONTEXT_PATH + "/changepassword?auth=" + token;
}
return emailService.sendToUser(EmailDetailsDto.builder().recipient(email).subject("Change password").messageBody(link).build())
? ResponseEntity.ok().build() : ResponseEntity.badRequest().build();
}
return ResponseEntity.badRequest().build();
}
Send email to user (sendToUser):
@Autowired
private JavaMailSender javaMailSender;
public boolean sendToUser(EmailDetailsDto emailDetailsDto) {
try {
// Creating a simple mail message
SimpleMailMessage mailMessage = new SimpleMailMessage();
// Setting up necessary details
mailMessage.setFrom(sender);
mailMessage.setTo(emailDetailsDto.getRecipient());
mailMessage.setText(emailDetailsDto.getMessageBody());
mailMessage.setSubject(emailDetailsDto.getSubject());
// Sending the mail
javaMailSender.send(mailMessage);
return true;
} catch (Exception e) {
log.error("failed to send email: " + e);
return false;
}
}
Here’s the function for generating the token
public String generateToken(String subject, long expiration) {
Date now = new Date();
Date expiryDate = new Date(now.getTime() + expiration);
return Jwts.builder().setSubject(subject).setIssuedAt(now)
.setExpiration(expiryDate).signWith(SignatureAlgorithm.HS256, Constants.JWT_SECRET).compact();
}
After the user receives the email, they will click on the link, and the token will be validated by this function
public boolean validateToken(String token) {
try {
Jwts.parser().setSigningKey(Constants.JWT_SECRET).parseClaimsJws(token);
return true;
} catch (MalformedJwtException e) {
log.error("Invalid JWT token");
} catch (ExpiredJwtException e) {
log.error("Expired JWT token");
} catch (UnsupportedJwtException e) {
log.error("Unsupported JWT token");
} catch (IllegalArgumentException e) {
log.error("JWT token is empty");
}
return false;
}
The JWT signature error occurs at the line
Jwts.parser().setSigningKey(Constants.JWT_SECRET).parseClaimsJws(token);
I’d read that the different signingKeys in generation and validation will lead to this error, but in my case, they’re the same and are Constants.JWT_SECRET
. The time is also in milliseconds, but i still get this error. Can anyone explain why? And how can i fix this?