Extend Security access to other entities in Springboot app
I have 3 tables. user table with id name email password and other details, dept table with deptid and deptname and checkin table for attendance(checkin, checkout). JWT was implemented for User table. When I'm trying to put/get into/from dept table i'm getting 403 forbidden error in postman. I'm unable to understand why since I've mentioned the paths of dept controller in securityconfig file. I haven't gone into checkin table yet. I ahve only configured it. Please help me to understand where I'm going wrong. these are my files: Entity Files: OurUsers.java @Entity @Table(name = "ourusers") @Data @EntityScan(basePackages = "com.ashville.usermanagementsystem.entity") public class OurUsers implements UserDetails { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer userId; @Column(unique = true, nullable = false) private String email; @Column(nullable = false) private String name; @Column(nullable = false) private String password; @Column(unique = true, nullable = false) private String mobile; private String city; private String role; @ManyToOne @JoinColumn(name = "dept_id", referencedColumnName = "departmentId") private Department department; @Override public Collection
I have 3 tables. user table with id name email password and other details, dept table with deptid and deptname and checkin table for attendance(checkin, checkout).
JWT was implemented for User table. When I'm trying to put/get into/from dept table i'm getting 403 forbidden error in postman. I'm unable to understand why since I've mentioned the paths of dept controller in securityconfig file. I haven't gone into checkin table yet. I ahve only configured it. Please help me to understand where I'm going wrong.
these are my files:
Entity Files:
OurUsers.java
@Entity
@Table(name = "ourusers")
@Data
@EntityScan(basePackages = "com.ashville.usermanagementsystem.entity")
public class OurUsers implements UserDetails {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer userId;
@Column(unique = true, nullable = false)
private String email;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private String password;
@Column(unique = true, nullable = false)
private String mobile;
private String city;
private String role;
@ManyToOne
@JoinColumn(name = "dept_id", referencedColumnName = "departmentId")
private Department department;
@Override
public Collection getAuthorities() {
return List.of(new SimpleGrantedAuthority(role));
}
public String getUsername() {
return email;
}
public OurUsers() {}
public OurUsers(Integer userId, String email, String password, String name, String mobile, String city, String role, Department department) {
this.userId = userId;
this.email = email;
this.password = password;
this.name = name;
this.mobile = mobile;
this.city = city;
this.role = role;
this.department = department;
}
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public Department getDepartment() {
return department;
}
public void setDepartment(Department department) {
this.department = department;
}}
Department.java
@Entity
@Table(name = "departments")
@EntityScan(basePackages = "com.ashville.usermanagementsystem.entity")
public class Department {
@Id
private Integer departmentId;
@Column(nullable = false, unique = true)
private String deptName;
@OneToMany(mappedBy = "department", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List users;
public Department() {}
public Department(String deptName) {
this.deptName = deptName;
}
public Integer getDepartmentId() {
return departmentId;
}
public void setDepartmentId(Integer departmentId) {
this.departmentId = departmentId;
}
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName = deptName;
}
public List getUsers() {
return users;
}
public void setUsers(List users) {
this.users = users;
}
}
Repository files UsersRepo.java
@EnableJpaRepositories(basePackages = "com.ashville.usermanagementsystem.repository")
public interface UsersRepo extends JpaRepository{
Optional findByEmail(String email);
DepartmentRepository.java
@Repository
@EnableJpaRepositories(basePackages = "com.ashville.usermanagementsystem.repository")
public interface DepartmentRepository extends JpaRepository {
List findByDepartmentId(Integer departmentId); // Find users by departmentId
void deleteByDepartmentId(Integer departmentId); // Delete users by departmentId
}
Service files OurUserDetailsService.java
package com.ashville.usermanagementsystem.services;
import java.util.List;
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;
import com.ashville.usermanagementsystem.entity.OurUsers;
import com.ashville.usermanagementsystem.repository.DepartmentRepository;
import com.ashville.usermanagementsystem.repository.UsersRepo;
@Service
public class OurUserDetailsService implements UserDetailsService {
@Autowired
private UsersRepo usersRepo;
@Autowired
private DepartmentRepository departmentRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
return usersRepo.findByEmail(username).orElseThrow();
}
public List getUsersByDepartmentId(Integer departmentId) {
return departmentRepository.findByDepartmentId(departmentId);
}
public void deleteUsersByDepartmentId(Integer departmentId) {
departmentRepository.deleteByDepartmentId(departmentId);
}
}
UserManagementService.java
@Service
public class UserManagementService {
@Autowired
private UsersRepo usersRepo;
@Autowired
private DepartmentRepository departmentRepository;
@Autowired
private JWTUtils jwtUtils;
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private PasswordEncoder passwordEncoder;
public RequestResponse register(RequestResponse registrationRequest){
RequestResponse resp = new RequestResponse();
try{
OurUsers ourUsers = new OurUsers();
ourUsers.setEmail(registrationRequest.getEmail());
ourUsers.setCity(registrationRequest.getCity());
ourUsers.setRole(registrationRequest.getRole());
ourUsers.setName(registrationRequest.getName());
ourUsers.setMobile(registrationRequest.getMobile());
ourUsers.setPassword(passwordEncoder.encode(registrationRequest.getPassword()));
OurUsers ourUsersResult = usersRepo.save(ourUsers);
if(ourUsersResult.getUserId()>0){
resp.setOurUsers(ourUsersResult);
System.out.println("User saved Successfully");
resp.setStatusCode(200);
}
}catch(Exception e){
resp.setStatusCode(500);
resp.setError(e.getMessage());
}
return resp;
}
public RequestResponse login(RequestResponse loginRequest){
RequestResponse response = new RequestResponse();
try{
authenticationManager
.authenticate(new UsernamePasswordAuthenticationToken(loginRequest.getEmail(),
loginRequest.getPassword()));
var user = usersRepo.findByEmail(loginRequest.getEmail()).orElseThrow();
var jwt = jwtUtils.generateToken(user);
var refreshToken = jwtUtils.generateRefreshToken(new HashMap<>(), user);
response.setStatusCode(200);
response.setToken(jwt);
response.setRefreshToken(refreshToken);
response.setExpirationTime("24Hrs");
System.out.println("Successfully Logged in");
}
catch(Exception e){
response.setStatusCode(500);
response.setError(e.getMessage());
}
return response;
}
public RequestResponse refreshToken(RequestResponse refreshTokenReqiest){
RequestResponse response = new RequestResponse();
try{
String ourEmail = jwtUtils.extractUsername(refreshTokenReqiest.getToken());
OurUsers users = usersRepo.findByEmail(ourEmail).orElseThrow();
if (jwtUtils.isTokenValid(refreshTokenReqiest.getToken(), users)) {
var jwt = jwtUtils.generateToken(users);
response.setStatusCode(200);
response.setToken(jwt);
response.setRefreshToken(refreshTokenReqiest.getToken());
response.setExpirationTime("24Hr");
System.out.println("Successfully Refreshed Token");
}
response.setStatusCode(200);
return response;
}catch (Exception e){
response.setStatusCode(500);
response.setError(e.getMessage());
return response;
}
}
public RequestResponse getAllUsers() {
RequestResponse reqRes = new RequestResponse();
try {
List result = usersRepo.findAll();
if (!result.isEmpty()) {
reqRes.setOurUsersList(result);
reqRes.setStatusCode(200);
System.out.println("Successfully Got All Users");
} else {
reqRes.setStatusCode(404);
reqRes.setError("No users found");
}
return reqRes;
} catch (Exception e) {
reqRes.setStatusCode(500);
reqRes.setError("Error occurred: " + e.getMessage());
return reqRes;
}
}
public RequestResponse getUsersById(Integer id) {
RequestResponse reqRes = new RequestResponse();
try {
OurUsers usersById = usersRepo.findById(id).orElseThrow(() -> new RuntimeException("User Not found"));
reqRes.setOurUsers(usersById);
reqRes.setStatusCode(200);
System.out.println("Users with id '" + id + "' found successfully");
} catch (Exception e) {
reqRes.setStatusCode(500);
reqRes.setError("Error occurred: " + e.getMessage());
}
return reqRes;
}
public RequestResponse deleteUser(Integer userId) {
RequestResponse reqRes = new RequestResponse();
try {
Optional userOptional = usersRepo.findById(userId);
if (userOptional.isPresent()) {
usersRepo.deleteById(userId);
reqRes.setStatusCode(200);
//reqRes.setMessage("User deleted successfully");
System.out.println("User deleted successfully");
} else {
reqRes.setStatusCode(404);
reqRes.setError("User not found for deletion");
}
} catch (Exception e) {
reqRes.setStatusCode(500);
reqRes.setError("Error occurred while deleting user: " + e.getMessage());
}
return reqRes;
}
public RequestResponse updateUser(Integer userId, OurUsers updatedUser) {
RequestResponse reqRes = new RequestResponse();
try {
Optional userOptional = usersRepo.findById(userId);
if (userOptional.isPresent()) {
OurUsers existingUser = userOptional.get();
existingUser.setEmail(updatedUser.getEmail());
existingUser.setName(updatedUser.getName());
existingUser.setCity(updatedUser.getCity());
existingUser.setRole(updatedUser.getRole());
if (updatedUser.getPassword() != null && !updatedUser.getPassword().isEmpty()) {
// Encode the password and update it
existingUser.setPassword(passwordEncoder.encode(updatedUser.getPassword()));
}
OurUsers savedUser = usersRepo.save(existingUser);
reqRes.setOurUsers(savedUser);
reqRes.setStatusCode(200);
System.out.println("User updated successfully");
} else {
reqRes.setStatusCode(404);
reqRes.setError("User not found for update");
}
} catch (Exception e) {
reqRes.setStatusCode(500);
reqRes.setError("Error occurred while updating user: " + e.getMessage());
}
return reqRes;
}
public RequestResponse getMyInfo(String email){
RequestResponse reqRes = new RequestResponse();
try {
Optional userOptional = usersRepo.findByEmail(email);
if (userOptional.isPresent()) {
reqRes.setOurUsers(userOptional.get());
reqRes.setStatusCode(200);
System.out.println("successful in getting my info");
//reqRes.setMessage("successful");
} else {
reqRes.setStatusCode(404);
reqRes.setError("User not found for update");
}
}catch (Exception e){
reqRes.setStatusCode(500);
reqRes.setError("Error occurred while getting user info: " + e.getMessage());
}
return reqRes;
}
public RequestResponse registerDept(RequestResponse registrationRequest){
RequestResponse resp = new RequestResponse();
try{
Department department = new Department();
department.setDeptName(registrationRequest.getDeptName());
Department departmentResult = departmentRepository.save(department);
if(departmentResult.getDepartmentId()>0){
resp.setDepartment(departmentResult);
System.out.println("Department saved Successfully");
resp.setStatusCode(200);
}
}catch(Exception e){
resp.setStatusCode(500);
resp.setError(e.getMessage());
}
return resp;
}
public RequestResponse getAllDepts() {
RequestResponse reqRes = new RequestResponse();
try {
List result = departmentRepository.findAll();
if (!result.isEmpty()) {
reqRes.setDepartmentList(result);
reqRes.setStatusCode(200);
System.out.println("Successfully Got All Depts");
} else {
reqRes.setStatusCode(404);
reqRes.setError("No depts found");
}
return reqRes;
} catch (Exception e) {
reqRes.setStatusCode(500);
reqRes.setError("Error occurred: " + e.getMessage());
return reqRes;
}
}
}
UserManagementController.java
@RestController
public class UserManagementController {
@Autowired
private UserManagementService userManagementService;
@Autowired
private OurUserDetailsService ourUserDetailsService;
@PostMapping("/auth/register")
public ResponseEntity register(@RequestBody RequestResponse res) {
return ResponseEntity.ok(userManagementService.register(res));
}
@PostMapping("/auth/login")
public ResponseEntity login(@RequestBody RequestResponse res) {
return ResponseEntity.ok(userManagementService.login(res));
}
@PostMapping("/auth/refresh")
public ResponseEntity refreshToken(@RequestBody RequestResponse res) {
return ResponseEntity.ok(userManagementService.refreshToken(res));
}
@GetMapping("/admin/get-all-users")
public ResponseEntity getAllUsers()
{
return ResponseEntity.ok(userManagementService.getAllUsers());
}
@GetMapping("/admin/get-users/{userId}")
public ResponseEntity getUserById(@PathVariable Integer userId)
{
return ResponseEntity.ok(userManagementService.getUsersById(userId));
}
@PutMapping("/admin/update/{userId}")
public ResponseEntity updateUser(@PathVariable Integer userId, @RequestBody OurUsers reqres)
{
return ResponseEntity.ok(userManagementService.updateUser(userId, reqres));
}
@GetMapping("/adminuser/get-profile")
public ResponseEntity getProfile()
{
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String email = authentication.getName();
RequestResponse response = userManagementService.getMyInfo(email);
return ResponseEntity.status(response.getStatusCode()).body(response);
}
@DeleteMapping("/admin/delete/{userId}")
public ResponseEntity deleteUSer(@PathVariable Integer userId){
return ResponseEntity.ok(userManagementService.deleteUser(userId));
}
@GetMapping("/department/{departmentId}")
public List getUsersByDepartment(@PathVariable Integer departmentId) {
return ourUserDetailsService.getUsersByDepartmentId(departmentId);
}
@DeleteMapping("/department/{departmentId}")
public void deleteUsersByDepartment(@PathVariable Integer departmentId) {
ourUserDetailsService.deleteUsersByDepartmentId(departmentId);
}}
DepartmentController.java
@RestController
@RequestMapping("/api/departments")
public class DepartmentController {
@Autowired
private UserManagementService userManagementService;
@Autowired
private DepartmentRepository departmentRepository;
@PostMapping("/admin/depts")
public ResponseEntity register(@RequestBody RequestResponse res) {
return ResponseEntity.ok(userManagementService.registerDept(res));
}
@GetMapping("/admin/get-all-depts")
public ResponseEntity getAllDepts()
{
return ResponseEntity.ok(userManagementService.getAllDepts());
}
@GetMapping("/admin/depts/{id}/users")
public List getUsersByDepartmentId(@PathVariable Integer id) {
return departmentRepository.findByDepartmentId(id);
}
@PutMapping("/admin/depts/{id}")
public ResponseEntity updateDepartment(@PathVariable Integer id, @RequestBody Department departmentDetails) {
Department department = departmentRepository.findById(id)
.orElseThrow(() -> new RuntimeException("Department not found"));
department.setDeptName(departmentDetails.getDeptName());
Department updatedDepartment = departmentRepository.save(department);
return ResponseEntity.ok(updatedDepartment);
}
@DeleteMapping("/admin/depts/{id}")
public ResponseEntity deleteDepartment(@PathVariable Integer id) {
departmentRepository.deleteById(id);
return ResponseEntity.ok().build();
}
}
Config Files
SecurityConfig.java
@Service
@EnableWebSecurity
public class SecurityConfig implements UserDetailsService {
@Autowired
private OurUserDetailsService ourUserDetailsService;
@Autowired
private JWTAuthFilter jwtAuthFilter;
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.csrf(AbstractHttpConfigurer::disable)
.cors(Customizer.withDefaults())
.authorizeHttpRequests(authz -> authz
.requestMatchers("/auth/**", "/public/**").permitAll()
.requestMatchers("/admin/**").hasAnyAuthority("ADMIN")
.requestMatchers("/user/**").hasAnyAuthority("USER")
.requestMatchers("/adminuser/**").hasAnyAuthority("ADMIN", "USER")
.anyRequest().authenticated())
.sessionManagement(session -> session
.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authenticationProvider(authenticationProvider())
.addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class);
return httpSecurity.build();
}
@Bean
public AuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
daoAuthenticationProvider.setUserDetailsService(ourUserDetailsService);
daoAuthenticationProvider.setPasswordEncoder(passwordEncoder());
return daoAuthenticationProvider;
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
throw new UnsupportedOperationException("Unimplemented method 'loadUserByUsername'");
}
}
JWTAuthFilter.java
@Component
public class JWTAuthFilter extends OncePerRequestFilter{
@Autowired
private JWTUtils jwtUtils;
@Autowired
private OurUserDetailsService ourUserDetailsService;
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException{
final String authHeader = request.getHeader("Authorization");
final String jwtToken;
final String userEmail;
if(authHeader == null || authHeader.isBlank()){
filterChain.doFilter(request, response);
return;
}
jwtToken = authHeader.substring(7);
userEmail = jwtUtils.extractUsername(jwtToken);
if(userEmail != null && SecurityContextHolder.getContext().getAuthentication() == null){
UserDetails userDetails = ourUserDetailsService.loadUserByUsername(userEmail);
if(jwtUtils.isTokenValid(jwtToken, userDetails)){
SecurityContext securityContext = SecurityContextHolder.createEmptyContext();
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
token.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
securityContext.setAuthentication(token);
SecurityContextHolder.setContext(securityContext);
}}
filterChain.doFilter(request, response); }}
CorsConfig.java
package com.ashville.usermanagementsystem.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CorsConfig {
@Bean
public WebMvcConfigurer webMvcConfigurer(){
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry){
registry.addMapping("/**")
.allowedMethods("GET","POST","PUT","DELETE")
.allowedOrigins("*");}};}}