JWT on login

This commit is contained in:
MathewFrancis 2025-05-15 11:54:32 +05:30
parent b9cfb42cc9
commit b328bc30a8
19 changed files with 125 additions and 173 deletions

View File

@ -9,11 +9,6 @@
18,2 18,2
18,1 18,1
18,0 18,0
16,4
16,3
16,2
16,1
16,0
14,4 14,4
14,3 14,3
14,2 14,2
@ -166,20 +161,18 @@
3,10 3,10
2,10 2,10
1,10 1,10
3,49
3,9 3,9
2,9 2,9
1,9 1,9
3,8 3,8
2,8 2,8
1,8 1,8
3,49
3,7 3,7
2,7 2,7
1,7 1,7
3,6 3,6
2,46
2,6 2,6
1,50
1,6 1,6
3,5 3,5
2,5 2,5

View File

@ -12,5 +12,7 @@ public interface UserOpsDAO {
public boolean checkIfAdminExists(UserEntity userEntity) throws Exception; public boolean checkIfAdminExists(UserEntity userEntity) throws Exception;
// admin login // admin login
public ReturnStatus adminSetPasswordToDb(UserEntity userEntity); public ReturnStatus adminSetUsernameAndPassword(UserEntity userEntity);
public UserEntity getUserByUserName(String userName);
} }

View File

@ -5,6 +5,7 @@ import com.example.cezenPBX.entity.user.Role;
import com.example.cezenPBX.entity.user.UserEntity; import com.example.cezenPBX.entity.user.UserEntity;
import jakarta.persistence.EntityManager; import jakarta.persistence.EntityManager;
import jakarta.persistence.Query; import jakarta.persistence.Query;
import jakarta.persistence.TypedQuery;
import jakarta.transaction.Transactional; import jakarta.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
@ -32,18 +33,19 @@ public class UserOpsDAOImpl implements UserOpsDAO{
// Admin sets a username and password for the first time // Admin sets a username and password for the first time
@Override @Override
@Transactional @Transactional
public ReturnStatus adminSetPasswordToDb(UserEntity userEntity) { public ReturnStatus adminSetUsernameAndPassword(UserEntity userEntity) {
try { try {
if (checkIfAdminExists(userEntity)) { if (checkIfAdminExists(userEntity)) {
return new ReturnStatus(false, "Admin already exists", ""); return new ReturnStatus(false, "Admin already exists", "");
} }
// Fetch existing ROLE_Admin from DB // Fetch existing ROLE_Admin from DB
Role adminRole = (Role) entityManager.createQuery("FROM Role r WHERE r.role = :roleName") TypedQuery<Role> query = entityManager.createQuery("FROM Role r WHERE r.role = :roleName", Role.class)
.setParameter("roleName", "ROLE_Admin") .setParameter("roleName", "ROLE_Admin");
.getSingleResult();
userEntity.setARole(adminRole); Role role = query.getSingleResult();
userEntity.setARole(role);
// Persist the user // Persist the user
entityManager.persist(userEntity); entityManager.persist(userEntity);
return new ReturnStatus(true, "Admin created", ""); return new ReturnStatus(true, "Admin created", "");
@ -51,4 +53,23 @@ public class UserOpsDAOImpl implements UserOpsDAO{
return new ReturnStatus(false, "Admin creation failed", e.getMessage()); return new ReturnStatus(false, "Admin creation failed", e.getMessage());
} }
} }
// get user details by username
// throws an exception if the user doesn't exist
// exception is caught and returns null ... custom authentication provider must catch the exception
@Override
public UserEntity getUserByUserName(String userName) {
try{
TypedQuery<UserEntity> query = this.entityManager
.createQuery("SELECT u FROM UserEntity u JOIN FETCH u.roles AS r WHERE u.userName = :userName", UserEntity.class);
query.setParameter("userName", userName);
return query.getSingleResult();
}catch ( Exception e){
return null;
}
}
} }

View File

@ -12,7 +12,7 @@ public record AdminSetPasswordDTO(
String email, String email,
@NotBlank(message = "Password cannot be blank") @NotBlank(message = "Password cannot be blank")
@Size(min = 8, message = "Password must be at least 8 characters long") @Size(min = 3, message = "Password must be at least 8 characters long")
String password, String password,
@NotBlank(message = "Confirm password cannot be blank") @NotBlank(message = "Confirm password cannot be blank")

View File

@ -6,7 +6,6 @@ import com.example.cezenPBX.security.JWTTokenValidatorFilter;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.Customizer; import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
@ -80,16 +79,17 @@ public class CezenLoginSecurityChain {
"/admin/list_all_branches_with_manager" "/admin/list_all_branches_with_manager"
).hasAnyRole("admin") ).hasAnyRole("admin")
//any one who is authenticated can access /logout //any one who is authenticated can access /logout
.requestMatchers("/bankUser/login", "/user/getXSRfToken", "/logout").authenticated() .requestMatchers("/open/login", "/user/getXSRfToken", "/logout").authenticated()
.requestMatchers("/bankUser/**").hasAnyRole("user") .requestMatchers("/bankUser/**").hasAnyRole("user")
//all the rest are open to public //all the rest are open to public
.requestMatchers("/open/**").permitAll() .requestMatchers("/open/signup").permitAll()
//.requestMatchers(HttpMethod.POST, "/open/**").permitAll() //.requestMatchers(HttpMethod.POST, "/open/**").permitAll()
) )
// redirect to /login if the user is not authenticated Customizer.withDefaults() enables a security feature using the defaults provided by Spring Security // redirect to /login if the user is not authenticated Customizer.withDefaults() enables a security feature using the defaults provided by Spring Security
.formLogin(Customizer.withDefaults()) .formLogin(Customizer.withDefaults())
.httpBasic(Customizer.withDefaults()); .httpBasic(Customizer.withDefaults());
System.out.print("Security chain configured");
return http.build(); return http.build();
} }

View File

@ -1,146 +1,81 @@
//package com.example.cezenPBX.config; package com.example.cezenPBX.config;
//
//import org.springframework.beans.factory.annotation.Autowired; import com.example.cezenPBX.DAO.UserOpsDAO;
//import org.springframework.security.authentication.AuthenticationProvider; import com.example.cezenPBX.entity.user.UserEntity;
//import org.springframework.security.authentication.BadCredentialsException; import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.authentication.AuthenticationProvider;
//import org.springframework.security.core.Authentication; import org.springframework.security.authentication.BadCredentialsException;
//import org.springframework.security.core.AuthenticationException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
//import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.Authentication;
//import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.AuthenticationException;
//import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.core.GrantedAuthority;
// import org.springframework.security.core.authority.SimpleGrantedAuthority;
//import java.util.ArrayList; import org.springframework.security.crypto.password.PasswordEncoder;
//import java.util.List; import org.springframework.stereotype.Component;
//
//public class CustomAuthenticationProviderForCezen implements AuthenticationProvider { import java.util.ArrayList;
// import java.util.List;
// @Autowired
// private UserRepository userRepository; @Component
// public class CustomAuthenticationProviderForCezen implements AuthenticationProvider {
// @Autowired
// private EmployeeRepository employeeRepository; @Autowired
// private UserOpsDAO userOpsDAO;
// @Autowired
// private PasswordEncoder passwordEncoder; @Autowired
// private PasswordEncoder passwordEncoder;
// @Override
// public Authentication authenticate(Authentication authentication) throws AuthenticationException { @Override
// public Authentication authenticate(Authentication authentication) throws AuthenticationException {
// //get credentials from login form
// String username = authentication.getName(); //get credentials from login form
// String pwd = authentication.getCredentials().toString(); String username = authentication.getName();
// String pwd = authentication.getCredentials().toString();
// //sanity check
// if (username.isEmpty() || pwd.isEmpty()) return null; //sanity check
// if (username.isEmpty() || pwd.isEmpty()) return null;
// System.out.println(pwd);
// System.out.println(username); //check for employee
// UserEntity user = null;
// int employeeId = 0; try {
// boolean isEmployee = false; //check if employee exists if yes then fetch details
// user = this.userOpsDAO.getUserByUserName(username);
// //what if the username is an employee login } catch (Exception e) {
// try { System.out.println(e.toString());
// //if true return null;
// employeeId = Integer.parseInt(username); }
// isEmployee = true;
// } catch (Exception e) { if (passwordEncoder.matches(pwd, user.getPassword())) {
// System.out.println(e.toString());
// } //then it is a match a number of springs granted authorities
// List<GrantedAuthority> authorities = new ArrayList<>();
// //employee auth
// if (isEmployee) { //loop through the users authorities and add each of them to simple granted authority
// // if it is a valid number range try {
// if (employeeId > 0) { //check if user is part of permission set for admin signing in
// //check for employee boolean isAdmin = false;
// Employee employee = null; for(var permission : user.getRoles()){
// try { if(permission.getRole().equals("ROLE_admin")) isAdmin = true;
// //check if employee exists if yes then fetch details }
// employee = employeeRepository.getEmployeeAndRolesById(employeeId); if(!isAdmin) throw new BadCredentialsException("no employee permission for given employee");
// } catch (Exception e) {
// System.out.println(e.toString()); user.getRoles().forEach(a -> authorities.add(new SimpleGrantedAuthority(a.getRole())));
// return null; } catch (Exception e) {
// } //use/**/r doesn't have permissions or roles = null
// System.out.println(e.toString());
// if (passwordEncoder.matches(pwd, employee.getPassword())) { return null;
// }
// //then it is a match a number of springs granted authorities
// List<GrantedAuthority> authorities = new ArrayList<>(); return new UsernamePasswordAuthenticationToken(user, pwd, authorities);
// } else {
// //loop through the users authorities and add each of them to simple granted authority throw new BadCredentialsException("Invalid password!");
// try { }
// }
// //check if employee is part of permission set for employee signing in
// boolean hasEmployee = false; @Override
// for(var permission : employee.getRoles()){ public boolean supports(Class<?> authentication) {
// if(permission.getRole().equals("ROLE_employee")) hasEmployee = true; //tells spring that i want to support username password style of auth
// } return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication));
// if(!hasEmployee) throw new BadCredentialsException("no employee permission for given employee"); }
//
// employee.getRoles().forEach(a -> authorities.add(new SimpleGrantedAuthority(a.getRole()))); }
// } catch (Exception e) {
// //use/**/r doesn't have permissions or roles = null
// System.out.println(e.toString());
// return null;
// }
//
// return new UsernamePasswordAuthenticationToken(employeeId, pwd, authorities);
// } else {
// throw new BadCredentialsException("Invalid password!");
// }
// } else {
// throw new BadCredentialsException("No user registered with this details!");
// }
//
// }
//
// //customer
// User customer = null;
// try {
// customer = userRepository.getUserDetailsByUserName(username);
//
// } catch (Exception e) {
// throw new BadCredentialsException("No user registered with this details!");
// }
//
// //if the person exists
// if (customer != null) {
// System.out.println(customer.getPassword());
//
// //check for a match
// if (passwordEncoder.matches(pwd, customer.getPassword())) {
//
// //then it is a match a number of springs granted authorities
// List<GrantedAuthority> authorities = new ArrayList<>();
//
// //loop through the users authorities and add each of them to simple granted authority
// try {
// customer.getRoles().forEach(a -> authorities.add(new SimpleGrantedAuthority(a.getRole())));
// } catch (Exception e) {
// //user doesn't have permissions or roles = null
// System.out.println(e.toString());
// return null;
// }
// //final send the username password and auth as a token which will call the authenticate method in the ProviderManager
// // in this edit i wont store the password but a use id
//
// //this is so that i can get a global access to an authenticated users name and id
// username = username + "," + customer.getId() + "," + customer.getUserAccountId().getId();
//
// return new UsernamePasswordAuthenticationToken(username, pwd, authorities);
// } else {
// throw new BadCredentialsException("Invalid password!");
// }
// } else {
// throw new BadCredentialsException("No user registered with this details!");
// }
// }
//
// @Override
// public boolean supports(Class<?> authentication) {
// //tells spring that i want to support username password style of auth
// return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication));
// }
//
//}

View File

@ -5,10 +5,7 @@ import com.example.cezenPBX.DTO.user.AdminSetPasswordDTO;
import com.example.cezenPBX.service.PbxUserService; import com.example.cezenPBX.service.PbxUserService;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController @RestController
@RequestMapping("/open") @RequestMapping("/open")
@ -30,6 +27,10 @@ public class SignUpController {
} }
// and a login route // and a login route
@GetMapping("/login")
public ReturnStatus login(){
return new ReturnStatus(false, "Login not yet implemented", "Login not yet implemented");
}

View File

@ -66,7 +66,8 @@ public class JWTTokenGeneratorFilter extends OncePerRequestFilter {
@Override @Override
protected boolean shouldNotFilter(HttpServletRequest request) { protected boolean shouldNotFilter(HttpServletRequest request) {
return (request.getServletPath().equals("/open/signup") || request.getServletPath().equals("/open/employee-login")); return !request.getServletPath().equals("/open/login");
//return !(request.getServletPath().equals("/open/signup") || request.getServletPath().equals("/open/login"));
} }
// gets the authority's from granted authority which we set in the configuration CustomAuthenticationProvider class // gets the authority's from granted authority which we set in the configuration CustomAuthenticationProvider class

View File

@ -74,7 +74,7 @@ public class JWTTokenValidatorFilter extends OncePerRequestFilter {
protected boolean shouldNotFilter(HttpServletRequest request) { protected boolean shouldNotFilter(HttpServletRequest request) {
return request.getServletPath().equals("/open/signup") return request.getServletPath().equals("/open/signup")
|| request.getServletPath().equals("/employee/employee-login"); || request.getServletPath().equals("/open/login");
// //bellow was done to archive this /exposed/** // //bellow was done to archive this /exposed/**
// request.getServletPath().split("/")[1].equals("exposed"); // request.getServletPath().split("/")[1].equals("exposed");
} }

View File

@ -2,7 +2,6 @@ package com.example.cezenPBX.service;
import com.example.cezenPBX.DAO.UserOpsDAO; import com.example.cezenPBX.DAO.UserOpsDAO;
import com.example.cezenPBX.DTO.ReturnStatus; import com.example.cezenPBX.DTO.ReturnStatus;
import com.example.cezenPBX.entity.user.Role;
import com.example.cezenPBX.entity.user.UserEntity; import com.example.cezenPBX.entity.user.UserEntity;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder;
@ -28,9 +27,9 @@ public class PbxUserService {
return new ReturnStatus(false, "Passwords do not match", "Passwords do not match"); return new ReturnStatus(false, "Passwords do not match", "Passwords do not match");
} }
// password encryption // password encryption
UserEntity userEntity = new UserEntity(userName, "{bcrypt}"+passwordEncoder.encode(password), email); UserEntity userEntity = new UserEntity(userName, passwordEncoder.encode(password), email);
// commit the username and password to the database // commit the username and password to the database
return userOpsDAO.adminSetPasswordToDb(userEntity); return userOpsDAO.adminSetUsernameAndPassword(userEntity);
} }
} }