this is my github https://github.com/carmmmm/antiFraudApplication
my POST is working, but my GET and DELETE requests don’t work. i think i am getting confused with the granted authortity, my Role enums, and how to get it all to work? im not sure why i am not getting it authenticated? I would appreciate any help!!
my user class
package antifraud.model;
import antifraud.enums.Role;
import antifraud.enums.UserStatus;
import jakarta.persistence.*;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
//Represents a user.
@Entity
@Table(name = "app_user")
public class User implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String name;
@Column(nullable = false, unique = true)
private String username;
@Column(nullable = false)
private String password;
@Enumerated(EnumType.STRING)
private Role role;
@Enumerated(EnumType.STRING)
private UserStatus status;
@Column(nullable = false)
private boolean isAccountLocked;
@ManyToMany
private final List<RoleUser> roles = new ArrayList<>();
public Collection<RoleUser> getRoles() {
return roles;
}
public User(String name, String username, String password, Role role, UserStatus status) {
this.id = id;
this.name = name;
this.username = username;
this.password = password;
this.role = role;
this.status = status;
}
public User() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Role getRole() {
return role;
}
public void setRole(Role role) {
this.role = role;
}
public UserStatus getStatus() {
return status;
}
public void setStatus(UserStatus status) {
this.status = status;
}
public boolean isAccountLocked() {
return isAccountLocked;
}
public void setAccountLocked(boolean accountNonLocked) {
isAccountLocked = accountNonLocked;
}
}
this is my security config class
package antifraud.config;
import antifraud.service.CustomUserDetailsService;
import antifraud.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.security.servlet.PathRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.http.HttpMethod;
import javax.management.relation.Role;
//Configures Spring Security.
@Configuration
@EnableWebSecurity
@EnableMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class SecurityConfig {
@Autowired
private CustomUserDetailsService customUserDetailsService;
@Autowired
private PasswordEncoder passwordEncoder;
// public SecurityConfig(AuthenticationEntryPoint restAuthenticationEntryPoint) {
// this.restAuthenticationEntryPoint = restAuthenticationEntryPoint;
// }
//
// void configure(AuthenticationManagerBuilder auth) throws Exception {
// auth.userDetailsService(userService).passwordEncoder(passwordEncoder);
// }
//
// protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// auth.userDetailsService(customUserDetailsService).passwordEncoder(passwordEncoder());
// }
// @Override
// protected void configure(HttpSecurity http) throws Exception {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http.csrf().disable()
.authorizeRequests()
.requestMatchers(HttpMethod.POST, "/api/auth/user").permitAll()
.requestMatchers(HttpMethod.DELETE, "/api/auth/user").hasRole("ADMINISTRATOR")
.requestMatchers(HttpMethod.GET, "/api/auth/list").hasAnyRole("ADMINISTRATOR", "MERCHANT", "SUPPORT")
.requestMatchers(HttpMethod.POST, "/api/antifraud/transaction").hasRole("MERCHANT")
.requestMatchers(HttpMethod.PUT, "/api/auth/access").hasRole("ADMINISTRATOR")
.requestMatchers(HttpMethod.PUT, "/api/auth/role").hasRole("ADMINISTRATOR")
.anyRequest().authenticated()
.and()
.formLogin().disable()
.httpBasic()
.and()
.build();
}
}
// private final AuthenticationEntryPoint restAuthenticationEntryPoint;
//
//
// public SecurityConfig(AuthenticationEntryPoint restAuthenticationEntryPoint) {
// this.restAuthenticationEntryPoint = restAuthenticationEntryPoint;
// }
//
// @Bean
// public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
// return http
// .httpBasic()
// .and()
// .csrf().disable()
// .exceptionHandling()
// .authenticationEntryPoint(restAuthenticationEntryPoint)
// .and()
// .headers().frameOptions().disable()
// .and()
// .authorizeRequests()
// .requestMatchers(HttpMethod.POST, "/api/auth/user").permitAll()
// .requestMatchers(HttpMethod.GET, "/api/auth/list").authenticated()
// .requestMatchers("/actuator/shutdown").permitAll()
// .requestMatchers("/h2-console/**").permitAll()
// .requestMatchers(PathRequest.toH2Console()).permitAll()
// .requestMatchers("/error").permitAll()
// .anyRequest().authenticated()
// .and()
// .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
// .and()
// .build();
// }
//
// @Bean
//// @Override
// protected UserDetailsService userDetailsService() {
// UserDetails user = User.withDefaultPasswordEncoder()
// .username("user")
// .password("password")
// .roles("USER")
// .build();
//
// return new InMemoryUserDetailsManager(user);
// }
my auth controller class
package antifraud.controller;
import antifraud.dtos.UserDTO;
import antifraud.dtos.UserRoleDto;
import antifraud.dtos.UserStatusDto;
import antifraud.enums.Role;
import antifraud.enums.UserStatus;
import antifraud.model.*;
import antifraud.repository.UserRepository;
import antifraud.exceptions.BadRequestException;
import antifraud.exceptions.ConflictException;
import antifraud.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.server.ResponseStatusException;
import javax.validation.Valid;
import java.util.List;
import java.util.stream.Collectors;
//Handles user registration, listing, and deletion.
@EnableMethodSecurity
@RestController
@RequestMapping("/api/auth")
public class AuthController {
@Autowired
private UserRepository userRepository;
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private UserService userService;
@PostMapping("/user")
public ResponseEntity<?> registerUser(@Valid @RequestBody User user) {
if (user.getUsername() == null || user.getPassword() == null|| user.getName() == null) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
}
if (userRepository.findByUsernameIgnoreCase(user.getUsername()).isPresent()) {
return ResponseEntity.status(HttpStatus.CONFLICT).body("User already exists");
}
// Determine role based on existing users
Role role = userRepository.count() == 0 ? Role.ADMINISTRATOR : Role.MERCHANT;
user.setRole(role);
// Set default locked status
user.setAccountLocked(role == Role.ADMINISTRATOR ? false : true);
// Encode the password and save the user
user.setPassword(passwordEncoder.encode(user.getPassword()));
User savedUser = userRepository.save(user);
// Prepare the response
UserDTO userDTO = new UserDTO(savedUser.getName(), savedUser.getUsername(), savedUser.getId(), savedUser.getRole());
return ResponseEntity.status(HttpStatus.CREATED).body(userDTO);
}
@PutMapping("/role")
public ResponseEntity<User> changeUserRole(@RequestBody UserRoleDto userRoleDto) throws ConflictException {
User user = userService.changeUserRole(userRoleDto.getUsername(), userRoleDto.getRole());
return new ResponseEntity<>(user, HttpStatus.OK);
}
@PutMapping("/access")
public ResponseEntity<StatusResponse> changeUserStatus(@RequestBody UserStatusDto userStatusDto) throws BadRequestException {
User user = userService.changeUserStatus(userStatusDto.getUsername(), UserStatus.valueOf(userStatusDto.getOperation()));
return new ResponseEntity<>(new StatusResponse("User " + user.getUsername() + " " + user.getStatus().name().toLowerCase() + "!"), HttpStatus.OK);
}
@GetMapping("/list")
@PreAuthorize("hasAnyRole('ADMINISTRATOR', 'MERCHANT', 'SUPPORT')")
public ResponseEntity<?> listUsers(@RequestBody User user) throws ConflictException {
if (user.getRole() != Role.ADMINISTRATOR || user.getRole() != Role.MERCHANT || user.getRole() != Role.SUPPORT) {
throw new ResponseStatusException(HttpStatus.FORBIDDEN);
}
List<User> userss = userRepository.findAll();
// Transform users to DTOs if needed
List<UserDTO> userDTOs = userss.stream()
.map(users -> new UserDTO(users.getName(), users.getUsername(), users.getId(), users.getRole()))
.collect(Collectors.toList());
userss.forEach(users -> System.out.println("Id: " + users.getId() + "User: " + users.getName() + " - " + users.getUsername() + "Role: " + users.getRole()));
return ResponseEntity.ok(userDTOs);
}
@DeleteMapping("/user/{username}")
public ResponseEntity<?> deleteUser(@PathVariable String username) {
User user = userRepository.findByUsernameIgnoreCase(username)
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "User not found"));
userRepository.delete(user);
return ResponseEntity.ok().body("{"username": "" + username + "", "status": "Deleted successfully!"}");
}
}
my custom user details service
package antifraud.service;
import antifraud.model.User;
import antifraud.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.stream.Collectors;
//Loads user details from the database for authentication.
@Service
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private UserRepository userRepository;
public CustomUserDetailsService(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsernameIgnoreCase(username)
.orElseThrow(() -> new UsernameNotFoundException("User not found"));
return new org.springframework.security.core.userdetails.User(
user.getUsername(),
user.getPassword(),
getAuthorities(user)
);
// return org.springframework.security.core.userdetails.User.withUsername(user.getUsername())
// .password(user.getPassword())
// .authorities(String.valueOf(user.getRole()))
// .build();
}
private Collection<? extends GrantedAuthority> getAuthorities(User user) {
return user.getRoles().stream()
.map(role -> new SimpleGrantedAuthority("ROLE_" + role))
.collect(Collectors.toList());
}
}
my user service
package antifraud.service;
import antifraud.exceptions.BadRequestException;
import antifraud.exceptions.ConflictException;
import antifraud.enums.Role;
import antifraud.enums.UserStatus;
import antifraud.model.User;
import antifraud.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
@Service
public class UserService implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsernameIgnoreCase(username)
.orElseThrow(() -> new UsernameNotFoundException("User not found"));
return org.springframework.security.core.userdetails.User.builder()
.username(user.getUsername())
.password(user.getPassword())
.roles(user.getRole().name())
.disabled(user.getStatus() == UserStatus.LOCKED)
.build();
}
public User registerUser(String name, String username, String password) {
Role role = userRepository.count() == 0 ? Role.ADMINISTRATOR : Role.MERCHANT;
UserStatus status = role == Role.ADMINISTRATOR ? UserStatus.ACTIVE : UserStatus.LOCKED;
User user = new User(name, username, password, role, status);
return userRepository.save(user);
}
public User changeUserRole(String username, Role newRole) throws ConflictException {
User user = userRepository.findByUsernameIgnoreCase(username).orElseThrow(() -> new UsernameNotFoundException("User not found"));
if (user.getRole() == newRole) {
throw new ConflictException("User already has the role " + newRole);
}
user.setRole(newRole);
return userRepository.save(user);
}
public User changeUserStatus(String username, UserStatus newStatus) throws BadRequestException {
User user = userRepository.findByUsernameIgnoreCase(username).orElseThrow(() -> new UsernameNotFoundException("User not found"));
if (user.getRole() == Role.ADMINISTRATOR) {
throw new BadRequestException("Cannot change status of ADMINISTRATOR");
}
user.setStatus(newStatus);
return userRepository.save(user);
}
}
I am using Postman for my requests and only my POST request works.
Carmen Montero is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.