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,1
18,0
16,4
16,3
16,2
16,1
16,0
14,4
14,3
14,2
@ -166,20 +161,18 @@
3,10
2,10
1,10
3,49
3,9
2,9
1,9
3,8
2,8
1,8
3,49
3,7
2,7
1,7
3,6
2,46
2,6
1,50
1,6
3,5
2,5

View File

@ -12,5 +12,7 @@ public interface UserOpsDAO {
public boolean checkIfAdminExists(UserEntity userEntity) throws Exception;
// 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 jakarta.persistence.EntityManager;
import jakarta.persistence.Query;
import jakarta.persistence.TypedQuery;
import jakarta.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
@ -32,18 +33,19 @@ public class UserOpsDAOImpl implements UserOpsDAO{
// Admin sets a username and password for the first time
@Override
@Transactional
public ReturnStatus adminSetPasswordToDb(UserEntity userEntity) {
public ReturnStatus adminSetUsernameAndPassword(UserEntity userEntity) {
try {
if (checkIfAdminExists(userEntity)) {
return new ReturnStatus(false, "Admin already exists", "");
}
// Fetch existing ROLE_Admin from DB
Role adminRole = (Role) entityManager.createQuery("FROM Role r WHERE r.role = :roleName")
.setParameter("roleName", "ROLE_Admin")
.getSingleResult();
TypedQuery<Role> query = entityManager.createQuery("FROM Role r WHERE r.role = :roleName", Role.class)
.setParameter("roleName", "ROLE_Admin");
userEntity.setARole(adminRole);
Role role = query.getSingleResult();
userEntity.setARole(role);
// Persist the user
entityManager.persist(userEntity);
return new ReturnStatus(true, "Admin created", "");
@ -51,4 +53,23 @@ public class UserOpsDAOImpl implements UserOpsDAO{
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,
@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,
@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 org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
@ -80,16 +79,17 @@ public class CezenLoginSecurityChain {
"/admin/list_all_branches_with_manager"
).hasAnyRole("admin")
//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")
//all the rest are open to public
.requestMatchers("/open/**").permitAll()
.requestMatchers("/open/signup").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
.formLogin(Customizer.withDefaults())
.httpBasic(Customizer.withDefaults());
System.out.print("Security chain configured");
return http.build();
}

View File

@ -1,146 +1,81 @@
//package com.example.cezenPBX.config;
//
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.security.authentication.AuthenticationProvider;
//import org.springframework.security.authentication.BadCredentialsException;
//import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
//import org.springframework.security.core.Authentication;
//import org.springframework.security.core.AuthenticationException;
//import org.springframework.security.core.GrantedAuthority;
//import org.springframework.security.core.authority.SimpleGrantedAuthority;
//import org.springframework.security.crypto.password.PasswordEncoder;
//
//import java.util.ArrayList;
//import java.util.List;
//
//public class CustomAuthenticationProviderForCezen implements AuthenticationProvider {
//
// @Autowired
// private UserRepository userRepository;
//
// @Autowired
// private EmployeeRepository employeeRepository;
//
// @Autowired
// private PasswordEncoder passwordEncoder;
//
// @Override
// public Authentication authenticate(Authentication authentication) throws AuthenticationException {
//
// //get credentials from login form
// String username = authentication.getName();
// String pwd = authentication.getCredentials().toString();
//
// //sanity check
// if (username.isEmpty() || pwd.isEmpty()) return null;
//
// System.out.println(pwd);
// System.out.println(username);
//
// int employeeId = 0;
// boolean isEmployee = false;
//
// //what if the username is an employee login
// try {
// //if true
// employeeId = Integer.parseInt(username);
// isEmployee = true;
// } catch (Exception e) {
// System.out.println(e.toString());
// }
//
// //employee auth
// if (isEmployee) {
// // if it is a valid number range
// if (employeeId > 0) {
// //check for employee
// Employee employee = null;
// try {
// //check if employee exists if yes then fetch details
// employee = employeeRepository.getEmployeeAndRolesById(employeeId);
// } catch (Exception e) {
// System.out.println(e.toString());
// return null;
// }
//
// if (passwordEncoder.matches(pwd, employee.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 {
//
// //check if employee is part of permission set for employee signing in
// boolean hasEmployee = false;
// for(var permission : employee.getRoles()){
// if(permission.getRole().equals("ROLE_employee")) hasEmployee = true;
// }
// 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));
// }
//
//}
package com.example.cezenPBX.config;
import com.example.cezenPBX.DAO.UserOpsDAO;
import com.example.cezenPBX.entity.user.UserEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
@Component
public class CustomAuthenticationProviderForCezen implements AuthenticationProvider {
@Autowired
private UserOpsDAO userOpsDAO;
@Autowired
private PasswordEncoder passwordEncoder;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
//get credentials from login form
String username = authentication.getName();
String pwd = authentication.getCredentials().toString();
//sanity check
if (username.isEmpty() || pwd.isEmpty()) return null;
//check for employee
UserEntity user = null;
try {
//check if employee exists if yes then fetch details
user = this.userOpsDAO.getUserByUserName(username);
} catch (Exception e) {
System.out.println(e.toString());
return null;
}
if (passwordEncoder.matches(pwd, user.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 {
//check if user is part of permission set for admin signing in
boolean isAdmin = false;
for(var permission : user.getRoles()){
if(permission.getRole().equals("ROLE_admin")) isAdmin = true;
}
if(!isAdmin) throw new BadCredentialsException("no employee permission for given employee");
user.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(user, pwd, authorities);
} else {
throw new BadCredentialsException("Invalid password!");
}
}
@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 jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/open")
@ -30,6 +27,10 @@ public class SignUpController {
}
// 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
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

View File

@ -74,7 +74,7 @@ public class JWTTokenValidatorFilter extends OncePerRequestFilter {
protected boolean shouldNotFilter(HttpServletRequest request) {
return request.getServletPath().equals("/open/signup")
|| request.getServletPath().equals("/employee/employee-login");
|| request.getServletPath().equals("/open/login");
// //bellow was done to archive this /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.DTO.ReturnStatus;
import com.example.cezenPBX.entity.user.Role;
import com.example.cezenPBX.entity.user.UserEntity;
import org.springframework.beans.factory.annotation.Autowired;
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");
}
// 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
return userOpsDAO.adminSetPasswordToDb(userEntity);
return userOpsDAO.adminSetUsernameAndPassword(userEntity);
}
}