How to test a reset password request with spring boot and postman? - spring-boot

I'm currently working on a reset password for users and I had a problem testing the method. This is the code below:
#PostMapping("/user/resetPassword")
public GenericResponse resetPassword(HttpServletRequest request, #RequestBody String userEmail) {
System.out.println("Here we are in the method of the reset *********");
User user = userRepository.findByEmail1(userEmail);
System.out.println ( user.getId());
System.out.println("This is my user"+user);
if (user == null) {
throw new UserNotFoundException();
}
String token = UUID.randomUUID().toString();
userService.createPasswordResetTokenForUser(user, token);
mailSender.send(constructResetTokenEmail(getAppUrl(request), request.getLocale(), token, user));
return new GenericResponse(messages.getMessage("message.resetPasswordEmail", null, request.getLocale()));
}
The problem is in the findByEmail it is not returning the user from the email that I am inserting in the JSON in the Postman payload:
User findByEmail(String email);
the result of the execution is UserNotFoundException.

Related

How to make register and login work correctly in spring security, problems with authentication

I'm trying to make authorization in my project. Registration works great and I get access and refresh tokens, but login throws an exception.
Problem is that in registration I create UsernamePasswordAuthenticationToken with UserEntity and password:
#PostMapping("/register")
public ResponseEntity register(#RequestBody UserSignUpModel userSignUpModel) {
UserEntity user = customUserDetailsService.createUser(userSignUpModel);
Authentication authentication = UsernamePasswordAuthenticationToken.authenticated(user, user.getPassword(), Collections.EMPTY_LIST);
return ResponseEntity.ok(tokenGenerator.createToken(authentication));
}
And in login I create UsernamePasswordAuthenticationToken with email and password so that the daoAuthenticationProvider can process it:
#PostMapping("/login")
public ResponseEntity login(#RequestBody UserSignInModel userSignInModel) {
Authentication authentication = daoAuthenticationProvider.authenticate(UsernamePasswordAuthenticationToken.unauthenticated(userSignInModel.getEmail(), userSignInModel.getPassword()));
return ResponseEntity.ok(tokenGenerator.createToken(authentication));
}
So I receive different authentication objects and can't pass the instanceoff check in TokenGenerator:
public TokenModel createToken(Authentication authentication) {
if (!(authentication.getPrincipal() instanceof UserEntity user)) {
throw new BadCredentialsException(
MessageFormat.format("principal {0} is not of UserEntity or UserDetails type", authentication.getPrincipal().getClass())
);
}
TokenModel tokenModel = new TokenModel();
tokenModel.setUserId(user.getUser_id());
tokenModel.setAccessToken(createAccessToken(authentication));
String refreshToken;
if (authentication.getCredentials() instanceof Jwt jwt) {
Instant now = Instant.now();
Instant expiresAt = jwt.getExpiresAt();
Duration duration = Duration.between(now, expiresAt);
long secondsUntilExpired = duration.toSeconds();
if (secondsUntilExpired < 15) {
refreshToken = createRefreshToken(authentication);
} else {
refreshToken = jwt.getTokenValue();
}
} else {
refreshToken = createRefreshToken(authentication);
}
tokenModel.setRefreshToken(refreshToken);
return tokenModel;
}
Should I write custom authentication provider? If so, do I need to download an entity from the repository and check passwords in it?

How to return a JWTtoken when users registers for the first time in springboot

I pretty new to Springboot with jwt, I need to generate a jwt token when users sign up for the first time and use the token to allow redirect to another page instead of returning user registered successfully message. How can I achieve this? I am able to generate a token when users signin and use the token for authentication. any help will be appreciated.
how am generating on signin method
#PostMapping("/signin")
public ResponseEntity<?> authenticateUser(#Valid #RequestBody LoginRequest loginRequest) {
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword()));
SecurityContextHolder.getContext().setAuthentication(authentication);
String jwt = jwtUtils.generateJwtToken(authentication);
UserDetailsImpl userDetails = (UserDetailsImpl) authentication.getPrincipal();
List<String> roles = userDetails.getAuthorities().stream()
.map(item -> item.getAuthority())
.collect(Collectors.toList());
return ResponseEntity.ok(new JwtResponse(jwt,
userDetails.getId(),
userDetails.getUsername(),
userDetails.getEmail(),
roles));
}
my signup method.
#PostMapping("/signup")
public ResponseEntity<?> registerUser(#Valid #RequestBody SignupRequest signUpRequest) {
if (userRepository.existsByUsername(signUpRequest.getUsername())) {
return ResponseEntity
.badRequest()
.body(new MessageResponse("Error: Username is already taken!"));
}
if (userRepository.existsByEmail(signUpRequest.getEmail())) {
return ResponseEntity
.badRequest()
.body(new MessageResponse("Error: Email is already in use!"));
}
// Create new user's account
User user = new User(signUpRequest.getUsername(), signUpRequest.getEmail(),
encoder.encode(signUpRequest.getPassword()),signUpRequest.getFirstname(),
signUpRequest.getSurname(),signUpRequest.getTelephoneno(),
signUpRequest.getWhatsappno());
Set<String> strRoles = signUpRequest.getRole();
Set<Role> roles = new HashSet<>();
if (strRoles == null) {
Role userRole = roleRepository.findByName(ERole.ROLE_USER)
.orElseThrow(() -> new RuntimeException("Error: Role is not found."));
roles.add(userRole);
} else {
strRoles.forEach(role -> {
switch (role) {
case "admin":
Role adminRole = roleRepository.findByName(ERole.ROLE_ADMIN)
.orElseThrow(() -> new RuntimeException("Error: Role is not found."));
roles.add(adminRole);
break;
case "mod":
Role modRole = roleRepository.findByName(ERole.ROLE_MODERATOR)
.orElseThrow(() -> new RuntimeException("Error: Role is not found."));
roles.add(modRole);
break;
default:
Role userRole = roleRepository.findByName(ERole.ROLE_USER)
.orElseThrow(() -> new RuntimeException("Error: Role is not found."));
roles.add(userRole);
}
});
}
user.setRoles(roles);
userRepository.save(user);
return ResponseEntity.ok(new MessageResponse("User registered successfully!"));
//return ResponseEntity.ok(jwt);
}
how can I generate a token when users sign instead of return ResponseEntity.ok(new MessageResponse("User registered successfully!"));

How to get the username (email in my case) in Spring Security [UserDetails/String]

I would like to get the e-mail which is username in my application to set the user which send a message. I decided to use typical method i.e. principal and getUsername():
#PostMapping("/messages/{id}")
#ResponseStatus(HttpStatus.CREATED)
public MessageDTO addOneMessage(#RequestBody MessageRequest messageRequest, #PathVariable ("id") Long id) {
checkIfChannelExists(id);
String content = messageRequest.getContent();
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String username = ((UserDetails) principal).getUsername();
Employee author = employeeRepository.findByEmail(username).get();
Message message = new Message(content, author, id);
messageRepository.save(message);
return new MessageDTO(message);
}
And MessageRequest.java:
#Data
#NoArgsConstructor
#AllArgsConstructor
public class MessageRequest {
#NonNull
private String content;
}
But, in this way I still get:
"message": "java.lang.String cannot be cast to org.springframework.security.core.userdetails.UserDetails"
What is wrong in my implementation? To be more precise, I use Postman to test POST requests:
{
"content": "something"
}
If you only need to retrieve the username you can get it through Authentication ie.
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String username = authentication.getName();
instead of typecasting to your class springcontext provide the almost all details about the user.
If you want the controller to get the user name to test.
please use this code.
//using authentication
#RequestMapping(value = "/name", method = RequestMethod.GET)
#ResponseBody
public String currentUserName(Authentication authentication) {
return authentication.name();
}
//using principal
#RequestMapping(value = "/name", method = RequestMethod.GET)
#ResponseBody
public String currentUserName(Principal principal) {
return principal.getName();
}

Login and get information user with token in spring (no OAuth)

I am implementing a project RESTful API, it should login (username / password) and returns a token, I want to use token to retrieve user information.
I follow the instructions:
https://github.com/virgo47/restful-spring-security
But: I do not know how to use it in my function, you can help me with?
#RequestMapping(value = "/login", method = RequestMethod.POST)
public #ResponseBody ResponseObject<Object> login(
#RequestParam(value = "username", required = true) String username,
#RequestParam(value = "password", required = true) String password,
#RequestHeader(value = "token") String token,
HttpSession session) {
//TODO
return new ResponseObject<Object>(1, "Success", data);
}
#RequestMapping(value = "/info", method = RequestMethod.GET)
public #ResponseBody ResponseObject<User> getInfo(#RequestHeader(value = "token", required = true) String token,
HttpSession session) {
//TODO
return null;
}
Why would you want to do that ? Why not just get the logged in user from the SecurityContext as follows
#RequestMapping(value = "/test", method = RequestMethod.GET)
public String test() {
System.out.println(" *** MainRestController.test");
// Spring Security dependency is unwanted in controller, typically some
// #Component (UserContext) hides it.
// Not that we don't use Spring Security annotations anyway...
return "SecurityContext: "
+ SecurityContextHolder.getContext().getAuthentication()
.getName();
}
If you insist on doing it, you can do the following.
UserDetails userDetails =
(UserDetails)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
tokenManager.getUserTokens(userDetails)

Spring MVC variable resets for no reason

For some reason when I execute a GET request to a certain URI the variable that I need to access in that method loses its memory or points to null.
I have a form where a user can update his personal information. But when he enters a duplicate, it redirects him to a page that lets him know
I have : private static volatile User currentUser;
This field is set when a user logs in and the server performs a GET request to a REST API, which I programmed myself, and returns the User containing his info. This works as expected and the user info is displayed on his home screen.
Code for the above:
#RequestMapping(value = "/login", method = RequestMethod.POST)
public String login(#ModelAttribute Credentials credentials,
RedirectAttributes redirect) {
RestTemplate restTemplate = new RestTemplate();
RoleInfo roleInfo = restTemplate.postForObject(
"http://localhost:9090/users/login", credentials,
RoleInfo.class);
if (roleInfo != null) {
if (roleInfo.isAdmin()) {
redirect.addFlashAttribute("credentials", credentials);
return "redirect:/adminHome";
} else {
redirect.addFlashAttribute("credentials", credentials);
return "redirect:/getBasicUser";
}
} else {
return "login_fail";
}
}
#RequestMapping(value = "/getBasicUser", method = RequestMethod.GET)
public <T> String getBasicUser(#ModelAttribute Credentials credentials,
Model model, RedirectAttributes redirect) {
RestTemplate restTemplate = new RestTemplate();
String url = "http://localhost:9090/users/getBasicUser?username="
+ credentials.getUsername();
ResponseEntity<User> responseEntity = restTemplate.exchange(
url,
HttpMethod.GET,
new HttpEntity<T>(createHeaders(credentials.getUsername(),
credentials.getPassword())), User.class);
User user;
user = responseEntity.getBody();
currentUser = user;
System.out.println("current user: " + currentUser.getUsername());
if (user != null) {
userName = credentials.getUsername();
passWord = credentials.getPassword();
redirect.addFlashAttribute("credentials", credentials);
redirect.addFlashAttribute("user", user);
return "redirect:/basicHome";
} else {
return "register_fail";
}
}
So on "basicHome" he can view his information. Also on that page is a link to a form where he can edit the information:
#RequestMapping(value = "/edit", method = RequestMethod.GET)
public String getEditProfilePage(Model model) {
model.addAttribute("currentUser", currentUser);
System.out.println("current use firstname: " + currentUser.getFirstname());
model.addAttribute("user", new User());
return "edit_profile";
}
If an edit is successful he is returned back to his home page with the updated information.
The problem comes when he enters invalid info. He should be redirected back to the "/edit" URI and the currentUserfield should still hold his information but is actually null.
Here is the "/edit" PUT function:
#RequestMapping(value = "/edit", method = RequestMethod.PUT)
public <T> String editProfile(#ModelAttribute("user") User user,
#ModelAttribute("credentials") Credentials credentials,
RedirectAttributes redirect) {
RestTemplate restTemplate = new RestTemplate();
String url = "http://localhost:9090/users/update?username=" + userName;
HttpHeaders headers = createHeaders(userName,
passWord);
#SuppressWarnings({ "unchecked", "rawtypes" })
HttpEntity<T> entity = new HttpEntity(user, headers);
ResponseEntity<User> responseEntity = restTemplate.exchange(url,
HttpMethod.PUT, entity, User.class);
User returnedUser = responseEntity.getBody();
currentUser = returnedUser;
if (returnedUser != null) {
redirect.addFlashAttribute("user", returnedUser);
redirect.addFlashAttribute("credentials", credentials);
return "redirect:/basicHome";
} else {
return "redirect:/editFail";
}
}
I figured out what I had to do. I basically made "user" a session object in: #SessionAttributes("user")

Resources