diff --git a/pom.xml b/pom.xml index db199065..8e39e65c 100644 --- a/pom.xml +++ b/pom.xml @@ -66,10 +66,10 @@ - - co.elastic.logging - logback-ecs-encoder - 1.3.2 + + co.elastic.logging + logback-ecs-encoder + 1.3.2 @@ -172,11 +172,28 @@ + + org.json json 20231013 + @@ -184,16 +201,16 @@ quartz 2.5.0-rc1 - - com.fasterxml.jackson.core - jackson-annotations - 2.17.0 - - - com.fasterxml.jackson.core - jackson-core - 2.17.0 - + + com.fasterxml.jackson.core + jackson-annotations + 2.17.0 + + + com.fasterxml.jackson.core + jackson-core + 2.17.0 + com.openkm sdk4j @@ -406,7 +423,7 @@ org.apache.xmlgraphics batik-all - + org.bouncycastle bcpkix-jdk15on @@ -423,7 +440,7 @@ org.apache.santuario xmlsec - + commons-io commons-io @@ -440,64 +457,45 @@ spring-web 6.1.6 + + + javax.ws.rs + javax.ws.rs-api + 2.1.1 + + + + + org.glassfish.jersey.core + jersey-common + 2.30.1 + + + org.glassfish.jersey.core + jersey-server + 2.30.1 + + + + + + org.glassfish.jersey.media + jersey-media-json-processing + 2.30.1 + + + + + org.glassfish.jaxb + jaxb-runtime + 2.3.1 + - - javax.ws.rs - javax.ws.rs-api - 2.1.1 - - - - - org.glassfish.jersey.core - jersey-common - 2.30.1 - - - org.glassfish.jersey.core - jersey-server - 2.30.1 - - - - - - org.glassfish.jersey.media - jersey-media-json-processing - 2.30.1 - - - - - org.glassfish.jaxb - jaxb-runtime - 2.3.1 - - - - io.jsonwebtoken - jjwt-api - 0.12.6 - - - - io.jsonwebtoken - jjwt-impl - 0.12.6 - runtime - - - - io.jsonwebtoken - jjwt-jackson - 0.12.6 - runtime - - commonapi-v3.0.0 + commonapi-v1.0 org.apache.maven.plugins @@ -574,7 +572,8 @@ ${target-properties} and ${source-properties} - diff --git a/src/main/environment/common_ci.properties b/src/main/environment/common_ci.properties index 1f82e9ea..067a79ac 100644 --- a/src/main/environment/common_ci.properties +++ b/src/main/environment/common_ci.properties @@ -140,13 +140,9 @@ eausadhaAuthorization= spring.main.allow-bean-definition-overriding=true spring.main.allow-circular-references=true -jwt.secret=@env.JWT_SECRET_KEY@ - - #ELK logging file name logging.file.name=@env.COMMON_API_LOGGING_FILE_NAME@ - ##grievance API call updateGrievanceDetails = @env.GRIEVANCE_API_BASE_URL@/grsbepro/igemr1097/public/api/v1/state-wise/grievance-list?page=PageNumber¤tpage=1 updateGrievanceTransactionDetails=@env.GRIEVANCE_API_BASE_URL@/grsbepro/igemr1097/public/api/v1/grievance_details/ diff --git a/src/main/environment/common_dev.properties b/src/main/environment/common_dev.properties index 597a8bf6..ca88de0c 100644 --- a/src/main/environment/common_dev.properties +++ b/src/main/environment/common_dev.properties @@ -170,7 +170,6 @@ spring.main.allow-bean-definition-overriding=true spring.main.allow-circular-references=true fileBasePath =/Doc -jwt.secret= ##grievance API call updateGrievanceDetails = /grsbepro/igemr1097/public/api/v1/state-wise/grievance-list?page=PageNumber¤tpage=1 diff --git a/src/main/environment/common_example.properties b/src/main/environment/common_example.properties index 9a90154d..22049952 100644 --- a/src/main/environment/common_example.properties +++ b/src/main/environment/common_example.properties @@ -168,8 +168,6 @@ eAusadhaUrl=https://dlc.kar.nic.in/e-services/api/DWInstituteInward eausadhaAuthorization= spring.main.allow-bean-definition-overriding=true spring.main.allow-circular-references=true -jwt.secret= - fileBasePath =/Doc ##grievance API call diff --git a/src/main/environment/common_test.properties b/src/main/environment/common_test.properties index df9007ee..84f4cb88 100644 --- a/src/main/environment/common_test.properties +++ b/src/main/environment/common_test.properties @@ -171,8 +171,6 @@ spring.main.allow-bean-definition-overriding=true spring.main.allow-circular-references=true fileBasePath =/Doc -jwt.secret= - ##grievance API call updateGrievanceDetails = /grsbepro/igemr1097/public/api/v1/state-wise/grievance-list?page=PageNumber¤tpage=1 diff --git a/src/main/environment/common_uat.properties b/src/main/environment/common_uat.properties index 92c55f4a..840cd97a 100644 --- a/src/main/environment/common_uat.properties +++ b/src/main/environment/common_uat.properties @@ -143,7 +143,6 @@ spring.main.allow-bean-definition-overriding=true spring.main.allow-circular-references=true fileBasePath =/Doc -jwt.secret= ##grievance API call updateGrievanceDetails = /grsbepro/igemr1097/public/api/v1/state-wise/grievance-list?page=PageNumber¤tpage=1 diff --git a/src/main/java/com/iemr/common/CommonApplication.java b/src/main/java/com/iemr/common/CommonApplication.java index 83078018..b1e03d41 100644 --- a/src/main/java/com/iemr/common/CommonApplication.java +++ b/src/main/java/com/iemr/common/CommonApplication.java @@ -22,18 +22,14 @@ package com.iemr.common; import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; import org.springframework.context.annotation.Bean; -import org.springframework.data.redis.connection.RedisConnectionFactory; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; -import org.springframework.data.redis.serializer.StringRedisSerializer; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.web.client.RestTemplate; -import com.iemr.common.data.users.User; import com.iemr.common.utils.IEMRApplBeans; @SpringBootApplication @@ -45,11 +41,11 @@ public IEMRApplBeans instantiateBeans() { return new IEMRApplBeans(); } - @Bean - public RestTemplate restTemplate() { - return new RestTemplate(); - } - + @Bean + public RestTemplate restTemplate() { + return new RestTemplate(); + } + public static void main(String[] args) { SpringApplication.run(CommonApplication.class, args); } @@ -58,19 +54,4 @@ protected SpringApplicationBuilder configure(SpringApplicationBuilder applicatio return application.sources(new Class[] { CommonApplication.class }); } - @Bean - public RedisTemplate redisTemplate(RedisConnectionFactory factory) { - RedisTemplate template = new RedisTemplate<>(); - template.setConnectionFactory(factory); - - // Use StringRedisSerializer for keys (userId) - template.setKeySerializer(new StringRedisSerializer()); - - // Use Jackson2JsonRedisSerializer for values (Users objects) - Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer<>(User.class); - template.setValueSerializer(serializer); - - return template; - } - } diff --git a/src/main/java/com/iemr/common/config/RedisConfig.java b/src/main/java/com/iemr/common/config/RedisConfig.java index faac71ae..ae1519e0 100644 --- a/src/main/java/com/iemr/common/config/RedisConfig.java +++ b/src/main/java/com/iemr/common/config/RedisConfig.java @@ -23,35 +23,14 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.data.redis.connection.RedisConnectionFactory; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; -import org.springframework.data.redis.serializer.StringRedisSerializer; import org.springframework.session.data.redis.config.ConfigureRedisAction; -import com.iemr.common.data.users.User; - @Configuration public class RedisConfig { - - @Bean - public ConfigureRedisAction configureRedisAction() { - return ConfigureRedisAction.NO_OP; - } - + @Bean - public RedisTemplate redisTemplate(RedisConnectionFactory factory) { - RedisTemplate template = new RedisTemplate<>(); - template.setConnectionFactory(factory); - - // Use StringRedisSerializer for keys (userId) - template.setKeySerializer(new StringRedisSerializer()); - - // Use Jackson2JsonRedisSerializer for values (Users objects) - Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer<>(User.class); - template.setValueSerializer(serializer); - - return template; - } + public ConfigureRedisAction configureRedisAction() { + return ConfigureRedisAction.NO_OP; + } } diff --git a/src/main/java/com/iemr/common/controller/users/IEMRAdminController.java b/src/main/java/com/iemr/common/controller/users/IEMRAdminController.java index e26f15dd..ffbb15df 100644 --- a/src/main/java/com/iemr/common/controller/users/IEMRAdminController.java +++ b/src/main/java/com/iemr/common/controller/users/IEMRAdminController.java @@ -21,23 +21,30 @@ */ package com.iemr.common.controller.users; -import java.util.*; -import java.util.concurrent.TimeUnit; +import java.security.NoSuchAlgorithmException; +import java.security.spec.InvalidKeySpecException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + import javax.ws.rs.core.MediaType; import com.iemr.common.utils.UserAgentUtil; -import io.jsonwebtoken.Claims; -import io.jsonwebtoken.ExpiredJwtException; import org.json.JSONArray; import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.gson.JsonElement; @@ -54,8 +61,7 @@ import com.iemr.common.model.user.ForceLogoutRequestModel; import com.iemr.common.model.user.LoginRequestModel; import com.iemr.common.service.users.IEMRAdminUserService; -import com.iemr.common.utils.CookieUtil; -import com.iemr.common.utils.JwtUtil; + import com.iemr.common.utils.encryption.AESUtil; import com.iemr.common.utils.exception.IEMRException; import com.iemr.common.utils.mapper.InputMapper; @@ -66,9 +72,7 @@ import io.lettuce.core.dynamic.annotation.Param; import io.swagger.v3.oas.annotations.Operation; -import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; @RequestMapping("/user") @RestController @@ -77,20 +81,16 @@ public class IEMRAdminController { private InputMapper inputMapper = new InputMapper(); private IEMRAdminUserService iemrAdminUserServiceImpl; - @Autowired - private JwtUtil jwtUtil; - @Autowired - private CookieUtil cookieUtil; - @Autowired - private RedisTemplate redisTemplate; + private AESUtil aesUtil; @Autowired public void setAesUtil(AESUtil aesUtil) { - this.aesUtil = aesUtil; + this.aesUtil = aesUtil; } + @Autowired public void setIemrAdminUserService(IEMRAdminUserService iemrAdminUserService) { this.iemrAdminUserServiceImpl = iemrAdminUserService; @@ -126,7 +126,7 @@ public String userAuthenticateNew( @RequestMapping(value = "/userAuthenticate", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON) public String userAuthenticate( @Param(value = "\"{\\\"userName\\\":\\\"String\\\",\\\"password\\\":\\\"String\\\"}\"") @RequestBody LoginRequestModel m_User, - HttpServletRequest request, HttpServletResponse httpResponse) { + HttpServletRequest request) { OutputResponse response = new OutputResponse(); logger.info("userAuthenticate request - " + m_User + " " + m_User.getUserName() + " " + m_User.getPassword()); try { @@ -138,9 +138,7 @@ public String userAuthenticate( JSONObject serviceRoleMap = new JSONObject(); JSONArray serviceRoleList = new JSONArray(); JSONObject previlegeObj = new JSONObject(); - if (m_User.getUserName() != null - && (m_User.getDoLogout() == null || !m_User.getDoLogout()) - && (m_User.getWithCredentials() != null && m_User.getWithCredentials())) { + if (m_User.getUserName() != null && (m_User.getDoLogout() == null || m_User.getDoLogout() == false)) { String tokenFromRedis = getConcurrentCheckSessionObjectAgainstUser( m_User.getUserName().trim().toLowerCase()); if (tokenFromRedis != null) { @@ -155,35 +153,6 @@ public String userAuthenticate( String refreshToken = null; boolean isMobile = false; if (mUser.size() == 1) { - jwtToken = jwtUtil.generateToken(m_User.getUserName(), mUser.get(0).getUserID().toString()); - - User user = new User(); // Assuming the Users class exists - user.setUserID(mUser.get(0).getUserID()); - user.setUserName(mUser.get(0).getUserName()); - - String userAgent = request.getHeader("User-Agent"); - isMobile = UserAgentUtil.isMobileDevice(userAgent); - logger.info("UserAgentUtil isMobile : " + isMobile); - - if (isMobile) { - refreshToken = jwtUtil.generateRefreshToken(m_User.getUserName(), user.getUserID().toString()); - logger.debug("Refresh token generated successfully for user: {}", user.getUserName()); - String jti = jwtUtil.getJtiFromToken(refreshToken); - redisTemplate.opsForValue().set( - "refresh:" + jti, - user.getUserID().toString(), - jwtUtil.getRefreshTokenExpiration(), - TimeUnit.MILLISECONDS - ); - } else { - cookieUtil.addJwtTokenToCookie(jwtToken, httpResponse, request); - } - - String redisKey = "user_" + mUser.get(0).getUserID(); // Use user ID to create a unique key - - // Store the user in Redis (set a TTL of 30 minutes) - redisTemplate.opsForValue().set(redisKey, user, 30, TimeUnit.MINUTES); - createUserMapping(mUser.get(0), resMap, serviceRoleMultiMap, serviceRoleMap, serviceRoleList, previlegeObj); } else { @@ -219,67 +188,6 @@ public String userAuthenticate( return response.toString(); } - @Operation(summary = "generating a auth token with the refreshToken.") - @RequestMapping(value = "/refreshToken", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON) - public ResponseEntity refreshToken(@RequestBody Map request) { - String refreshToken = request.get("refreshToken"); - - try { - if (jwtUtil.validateToken(refreshToken) == null) { - return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Invalid token"); - } - - Claims claims = jwtUtil.getAllClaimsFromToken(refreshToken); - - // Verify token type - if (!"refresh".equals(claims.get("token_type", String.class))) { - return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Invalid token type"); - } - - // Check revocation using JTI - String jti = claims.getId(); - if (!redisTemplate.hasKey("refresh:" + jti)) { - return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Token revoked"); - } - - // Get user details - // Get user details - String userId = claims.get("userId", String.class); - User user = iemrAdminUserServiceImpl.getUserById(Long.parseLong(userId)); - - // Validate that the user still exists and is active - if (user == null) { - return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("User not found"); - } - - if (user.getM_status() == null || !"Active".equalsIgnoreCase(user.getM_status().getStatus())) { - return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("User account is inactive"); - } - // Generate new tokens - String newJwt = jwtUtil.generateToken(user.getUserName(), userId); - - Map tokens = new HashMap<>(); - tokens.put("jwtToken", newJwt); - - // Generate and store a new refresh token (token rotation) - String newRefreshToken = jwtUtil.generateRefreshToken(user.getUserName(), userId); - String newJti = jwtUtil.getJtiFromToken(newRefreshToken); - redisTemplate.opsForValue().set( - "refresh:" + newJti, - userId, - jwtUtil.getRefreshTokenExpiration(), - TimeUnit.MILLISECONDS - ); - tokens.put("refreshToken", newRefreshToken); - - return ResponseEntity.ok(tokens); - } catch (ExpiredJwtException ex) { - return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Token expired"); - } catch (Exception e) { - logger.error("Refresh failed: ", e); - return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Token refresh failed"); - } - } @CrossOrigin() @Operation(summary = "Log out user from concurrent session") @@ -374,11 +282,11 @@ private void createUserMapping(User mUser, JSONObject resMap, JSONObject service previlegeObj.getJSONObject(serv).put("agentID", m_UserServiceRoleMapping.getAgentID()); previlegeObj.getJSONObject(serv).put("agentPassword", m_UserServiceRoleMapping.getAgentPassword()); } - JSONArray roles = previlegeObj.getJSONObject(serv).getJSONArray("roles"); + JSONArray roles = previlegeObj.getJSONObject(serv).getJSONArray("roles"); // roles.put(new JSONObject(m_UserServiceRoleMapping.getM_Role().toString())); - JSONObject roleObject = new JSONObject(m_UserServiceRoleMapping.getM_Role().toString()); - roleObject.put("isSanjeevani", m_UserServiceRoleMapping.getIsSanjeevani()); - roles.put(roleObject); + JSONObject roleObject = new JSONObject(m_UserServiceRoleMapping.getM_Role().toString()); + roleObject.put("isSanjeevani", m_UserServiceRoleMapping.getIsSanjeevani()); + roles.put(roleObject); } Iterator keySet = serviceRoleMultiMap.keys(); while (keySet.hasNext()) { @@ -696,9 +604,8 @@ public String getRoleScreenMappingByProviderID( logger.info("getRoleScreenMappingByProviderID"); try { ObjectMapper objectMapper = new ObjectMapper(); - ServiceRoleScreenMapping serviceRoleScreenMapping = objectMapper.readValue(request, - ServiceRoleScreenMapping.class); - + ServiceRoleScreenMapping serviceRoleScreenMapping = objectMapper.readValue(request, ServiceRoleScreenMapping.class); + List mapping = iemrAdminUserServiceImpl .getUserServiceRoleMappingForProvider(serviceRoleScreenMapping.getProviderServiceMapID()); @@ -717,9 +624,10 @@ public String getRoleScreenMappingByProviderID( */) @Operation(summary = "Get users by provider id") @RequestMapping(value = "/getUsersByProviderID", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON, headers = "Authorization") - public String getUsersByProviderID(@Param(value = "{\"providerServiceMapID\":\"Integer - providerServiceMapID\", " - + "\"RoleID\":\"Optional: Integer - role ID to be filtered\", " - + "\"languageName\":\"Optional: String - languageName\"}") @RequestBody String request) { + public String getUsersByProviderID( + @Param(value = "{\"providerServiceMapID\":\"Integer - providerServiceMapID\", " + + "\"RoleID\":\"Optional: Integer - role ID to be filtered\", " + + "\"languageName\":\"Optional: String - languageName\"}") @RequestBody String request) { OutputResponse response = new OutputResponse(); logger.info("getRolesByProviderID request "); try { @@ -992,9 +900,8 @@ public String userAuthenticateBhavya( OutputResponse response = new OutputResponse(); logger.info("userAuthenticate request - " + m_User + " " + m_User.getUserName() + " " + m_User.getPassword()); try { - // String decryptPassword = aesUtil.decrypt("Piramal12Piramal", - // m_User.getPassword()); - // logger.info("decryptPassword : " + m_User.getPassword()); + //String decryptPassword = aesUtil.decrypt("Piramal12Piramal", m_User.getPassword()); + //logger.info("decryptPassword : " + m_User.getPassword()); List mUser = iemrAdminUserServiceImpl.userAuthenticate(m_User.getUserName(), m_User.getPassword()); JSONObject resMap = new JSONObject(); JSONObject serviceRoleMultiMap = new JSONObject(); @@ -1040,22 +947,4 @@ public String userAuthenticateBhavya( return response.toString(); } - @GetMapping("/get-jwt-token") - public ResponseEntity getJwtTokenFromCookie(HttpServletRequest httpRequest) { - // Retrieve the cookie named 'jwtToken' - Cookie[] cookies = httpRequest.getCookies(); - - if (cookies != null) { - for (Cookie cookie : cookies) { - if ("jwtToken".equals(cookie.getName())) { - String jwtToken = cookie.getValue(); - // Return the JWT token in the response - return ResponseEntity.ok(jwtToken); - } - } - } - // Return 404 if the token is not found in the cookies - return ResponseEntity.status(HttpStatus.NOT_FOUND).body("JWT token not found"); - } - } diff --git a/src/main/java/com/iemr/common/data/users/User.java b/src/main/java/com/iemr/common/data/users/User.java index 4710b11d..d4030347 100644 --- a/src/main/java/com/iemr/common/data/users/User.java +++ b/src/main/java/com/iemr/common/data/users/User.java @@ -21,13 +21,11 @@ */ package com.iemr.common.data.users; -import java.io.Serializable; import java.sql.Timestamp; import java.util.List; import java.util.Set; import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.google.gson.annotations.Expose; import com.iemr.common.data.callhandling.OutboundCallRequest; import com.iemr.common.data.feedback.FeedbackDetails; @@ -54,7 +52,7 @@ @Entity @Table(name = "m_user") @Data -public class User implements Serializable { +public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Expose @@ -196,7 +194,6 @@ public class User implements Serializable { private String newPassword = null; @Transient - @JsonIgnore private OutputMapper outPutMapper = new OutputMapper(); // new field for rate-limit, failed authentication diff --git a/src/main/java/com/iemr/common/model/user/LoginRequestModel.java b/src/main/java/com/iemr/common/model/user/LoginRequestModel.java index 81308b49..770eaeb4 100644 --- a/src/main/java/com/iemr/common/model/user/LoginRequestModel.java +++ b/src/main/java/com/iemr/common/model/user/LoginRequestModel.java @@ -25,21 +25,23 @@ import lombok.EqualsAndHashCode; @EqualsAndHashCode(exclude = { "authKey" }) -public @Data class LoginRequestModel { +public @Data class LoginRequestModel +{ private String userName; private String password; private String authKey; private Boolean doLogout; - private Boolean withCredentials; - + + + public LoginRequestModel() { - + } - - // everwell-1097 registration + //everwell-1097 registration public LoginRequestModel(String userName, String password) { this.userName = userName; this.password = password; } - + + } diff --git a/src/main/java/com/iemr/common/service/users/IEMRAdminUserService.java b/src/main/java/com/iemr/common/service/users/IEMRAdminUserService.java index 3f1d8068..685ffc9b 100644 --- a/src/main/java/com/iemr/common/service/users/IEMRAdminUserService.java +++ b/src/main/java/com/iemr/common/service/users/IEMRAdminUserService.java @@ -115,9 +115,5 @@ public List getUserServiceRoleMappingForProvider(Integ int setForgetPassword(User user, String loginpass, String transactionId, Boolean isAdmin) throws IEMRException; String generateTransactionIdForPasswordChange(User user) throws Exception; - - User getUserById(Long userId) throws IEMRException; - - } diff --git a/src/main/java/com/iemr/common/service/users/IEMRAdminUserServiceImpl.java b/src/main/java/com/iemr/common/service/users/IEMRAdminUserServiceImpl.java index a9a7858d..772a669a 100644 --- a/src/main/java/com/iemr/common/service/users/IEMRAdminUserServiceImpl.java +++ b/src/main/java/com/iemr/common/service/users/IEMRAdminUserServiceImpl.java @@ -1171,22 +1171,5 @@ private String toHex(byte[] array) throws NoSuchAlgorithmException { } return hex; } - - public User getUserById(Long userId) throws IEMRException { - try { - // Fetch user from custom repository by userId - User user = iEMRUserRepositoryCustom.findByUserID(userId); - - // Check if user is found - if (user == null) { - throw new IEMRException("User not found with ID: " + userId); - } - - return user; - } catch (Exception e) { - // Log and throw custom exception in case of errors - logger.error("Error fetching user with ID: " + userId, e); - throw new IEMRException("Error fetching user with ID: " + userId, e); - } - } + } diff --git a/src/main/java/com/iemr/common/utils/CookieUtil.java b/src/main/java/com/iemr/common/utils/CookieUtil.java deleted file mode 100644 index 678f639c..00000000 --- a/src/main/java/com/iemr/common/utils/CookieUtil.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.iemr.common.utils; - -import java.util.Arrays; -import java.util.Optional; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Service; - -import jakarta.servlet.http.Cookie; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; - -@Service -public class CookieUtil { - - @Value("${isProduction}") - private Boolean isProduction; - - public Optional getCookieValue(HttpServletRequest request, String cookieName) { - Cookie[] cookies = request.getCookies(); - if (cookies != null) { - for (Cookie cookie : cookies) { - if (cookieName.equals(cookie.getName())) { - return Optional.of(cookie.getValue()); - } - } - } - return Optional.empty(); - } - - public void addJwtTokenToCookie(String Jwttoken, HttpServletResponse response, HttpServletRequest request) { - // Create a new cookie with the JWT token - Cookie cookie = new Cookie("Jwttoken", Jwttoken); - - // Make the cookie HttpOnly to prevent JavaScript access for security - cookie.setHttpOnly(true); - - // Set the Max-Age (expiry time) in seconds (1 day) - cookie.setMaxAge(60 * 60 * 24); // 1 day expiration - - // Set the path to "/" so the cookie is available across the entire application - cookie.setPath("/"); - - // Set the SameSite attribute for cross-site request handling (if needed) - String sameSite = "None"; // Allow cross-site cookies (can be 'Strict', 'Lax', or 'None') - if(isProduction) { - sameSite= "Strict"; - } - cookie.setSecure(true); - - // Build the Set-Cookie header manually (to add SameSite attribute support) - StringBuilder cookieHeader = new StringBuilder(); - cookieHeader.append(cookie.getName()).append("=").append(cookie.getValue()) - .append("; Path=").append(cookie.getPath()) - .append("; Max-Age=").append(cookie.getMaxAge()) - .append("; HttpOnly"); - - // Add SameSite and Secure attributes manually if needed - cookieHeader.append("; SameSite=").append(sameSite); - if (cookie.getSecure()) { - cookieHeader.append("; Secure"); - } - - // Set the custom Set-Cookie header - response.addHeader("Set-Cookie", cookieHeader.toString()); - } - - public String getJwtTokenFromCookie(HttpServletRequest request) { - if (request.getCookies() == null) { - return null; // If cookies are null, return null safely. - } - return Arrays.stream(request.getCookies()).filter(cookie -> "Jwttoken".equals(cookie.getName())) - .map(Cookie::getValue).findFirst().orElse(null); - } -} diff --git a/src/main/java/com/iemr/common/utils/FilterConfig.java b/src/main/java/com/iemr/common/utils/FilterConfig.java deleted file mode 100644 index 1f15a7fa..00000000 --- a/src/main/java/com/iemr/common/utils/FilterConfig.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.iemr.common.utils; - -import org.springframework.boot.web.servlet.FilterRegistrationBean; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -@Configuration -public class FilterConfig { - - @Bean - public FilterRegistrationBean jwtUserIdValidationFilter( - JwtAuthenticationUtil jwtAuthenticationUtil) { - FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); - registrationBean.setFilter(new JwtUserIdValidationFilter(jwtAuthenticationUtil)); - registrationBean.addUrlPatterns("/*"); // Apply filter to all API endpoints - return registrationBean; - } - -} diff --git a/src/main/java/com/iemr/common/utils/JwtAuthenticationUtil.java b/src/main/java/com/iemr/common/utils/JwtAuthenticationUtil.java deleted file mode 100644 index c9e27459..00000000 --- a/src/main/java/com/iemr/common/utils/JwtAuthenticationUtil.java +++ /dev/null @@ -1,130 +0,0 @@ -package com.iemr.common.utils; - -import java.util.Optional; -import java.util.concurrent.TimeUnit; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Component; - -import com.iemr.common.data.users.User; -import com.iemr.common.repository.users.IEMRUserRepositoryCustom; -import com.iemr.common.service.users.IEMRAdminUserServiceImpl; -import com.iemr.common.utils.exception.IEMRException; - -import io.jsonwebtoken.Claims; -import jakarta.servlet.http.HttpServletRequest; - -@Component -public class JwtAuthenticationUtil { - - @Autowired - private CookieUtil cookieUtil; - @Autowired - private JwtUtil jwtUtil; - @Autowired - private RedisTemplate redisTemplate; - @Autowired - private IEMRUserRepositoryCustom iEMRUserRepositoryCustom; - private final Logger logger = LoggerFactory.getLogger(this.getClass().getName()); - - @Autowired - private IEMRAdminUserServiceImpl iEMRAdminUserServiceImpl; - - public JwtAuthenticationUtil(CookieUtil cookieUtil, JwtUtil jwtUtil) { - this.cookieUtil = cookieUtil; - this.jwtUtil = jwtUtil; - } - - public ResponseEntity validateJwtToken(HttpServletRequest request) { - Optional jwtTokenOpt = cookieUtil.getCookieValue(request, "Jwttoken"); - - if (jwtTokenOpt.isEmpty()) { - return ResponseEntity.status(HttpStatus.UNAUTHORIZED) - .body("Error 401: Unauthorized - JWT Token is not set!"); - } - - String jwtToken = jwtTokenOpt.get(); - - // Validate the token - Claims claims = jwtUtil.validateToken(jwtToken); - if (claims == null) { - return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Error 401: Unauthorized - Invalid JWT Token!"); - } - - // Extract username from token - String usernameFromToken = claims.getSubject(); - if (usernameFromToken == null || usernameFromToken.isEmpty()) { - return ResponseEntity.status(HttpStatus.UNAUTHORIZED) - .body("Error 401: Unauthorized - Username is missing!"); - } - - // Return the username if valid - return ResponseEntity.ok(usernameFromToken); - } - - public boolean validateUserIdAndJwtToken(String jwtToken) throws IEMRException { - try { - // Validate JWT token and extract claims - Claims claims = jwtUtil.validateToken(jwtToken); - - if (claims == null) { - throw new IEMRException("Invalid JWT token."); - } - - String userId = claims.get("userId", String.class); - - // Check if user data is present in Redis - User user = getUserFromCache(userId); - if (user == null) { - // If not in Redis, fetch from DB and cache the result - user = fetchUserFromDB(userId); - } - if (user == null) { - throw new IEMRException("Invalid User ID."); - } - - return true; // Valid userId and JWT token - } catch (Exception e) { - logger.error("Validation failed: " + e.getMessage(), e); - throw new IEMRException("Validation error: " + e.getMessage(), e); - } - } - - private User getUserFromCache(String userId) { - String redisKey = "user_" + userId; // The Redis key format - User user = (User) redisTemplate.opsForValue().get(redisKey); - - if (user == null) { - logger.warn("User not found in Redis. Will try to fetch from DB."); - } else { - logger.info("User fetched successfully from Redis."); - } - - return user; // Returns null if not found - } - - private User fetchUserFromDB(String userId) { - // This method will only be called if the user is not found in Redis. - String redisKey = "user_" + userId; // Redis key format - - // Fetch user from DB - User user = iEMRUserRepositoryCustom.findByUserID(Long.parseLong(userId)); - - if (user != null) { - // Cache the user in Redis for future requests (cache for 30 minutes) - redisTemplate.opsForValue().set(redisKey, user, 30, TimeUnit.MINUTES); - - // Log that the user has been stored in Redis - logger.info("User stored in Redis with key: " + redisKey); - } else { - logger.warn("User not found for userId: " + userId); - } - - return user; - } -} diff --git a/src/main/java/com/iemr/common/utils/JwtUserIdValidationFilter.java b/src/main/java/com/iemr/common/utils/JwtUserIdValidationFilter.java deleted file mode 100644 index b83f4873..00000000 --- a/src/main/java/com/iemr/common/utils/JwtUserIdValidationFilter.java +++ /dev/null @@ -1,120 +0,0 @@ -package com.iemr.common.utils; - -import java.io.IOException; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import jakarta.servlet.Filter; -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.ServletRequest; -import jakarta.servlet.ServletResponse; -import jakarta.servlet.http.Cookie; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; - -@Component -public class JwtUserIdValidationFilter implements Filter { - - private final JwtAuthenticationUtil jwtAuthenticationUtil; - private final Logger logger = LoggerFactory.getLogger(this.getClass().getName()); - - public JwtUserIdValidationFilter(JwtAuthenticationUtil jwtAuthenticationUtil) { - this.jwtAuthenticationUtil = jwtAuthenticationUtil; - } - - @Override - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) - throws IOException, ServletException { - HttpServletRequest request = (HttpServletRequest) servletRequest; - HttpServletResponse response = (HttpServletResponse) servletResponse; - - String path = request.getRequestURI(); - String contextPath = request.getContextPath(); - logger.info("JwtUserIdValidationFilter invoked for path: " + path); - - // Log cookies for debugging - Cookie[] cookies = request.getCookies(); - if (cookies != null) { - for (Cookie cookie : cookies) { - if ("userId".equals(cookie.getName())) { - logger.warn("userId found in cookies! Clearing it..."); - clearUserIdCookie(response); // Explicitly remove userId cookie - } - } - } else { - logger.info("No cookies found in the request"); - } - - // Log headers for debugging - String jwtTokenFromHeader = request.getHeader("Jwttoken"); - logger.info("JWT token from header: "); - - // Skip authentication for public endpoints - if (shouldSkipAuthentication(path, contextPath)) { - logger.info("Skipping filter for path: {}", path); - filterChain.doFilter(servletRequest, servletResponse); - return; - } - - try { - // Retrieve JWT token from cookies - String jwtTokenFromCookie = getJwtTokenFromCookies(request); - logger.info("JWT token from cookie: "); - - // Determine which token (cookie or header) to validate - String jwtToken = jwtTokenFromCookie != null ? jwtTokenFromCookie : jwtTokenFromHeader; - if (jwtToken == null) { - logger.error("JWT token not found in cookies or headers"); - response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "JWT token not found in cookies or headers"); - return; - } - - // Validate JWT token and userId - if (jwtAuthenticationUtil.validateUserIdAndJwtToken(jwtToken)) { - // If token is valid, allow the request to proceed - logger.info("Valid JWT token"); - filterChain.doFilter(servletRequest, servletResponse); - } else { - logger.error("Invalid JWT token"); - response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Invalid JWT token"); - } - } catch (Exception e) { - logger.error("Authorization error: ", e); - response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Authorization error: " + e.getMessage()); - } - } - - private boolean shouldSkipAuthentication(String path, String contextPath) { - return path.equals(contextPath + "/user/userAuthenticate") - || path.equalsIgnoreCase(contextPath + "/user/logOutUserFromConcurrentSession") - || path.startsWith(contextPath + "/swagger-ui") - || path.startsWith(contextPath + "/v3/api-docs") - || path.startsWith(contextPath + "/public") - || path.equals(contextPath + "/user/refreshToken") - ; - } - - private String getJwtTokenFromCookies(HttpServletRequest request) { - Cookie[] cookies = request.getCookies(); - if (cookies != null) { - for (Cookie cookie : cookies) { - if (cookie.getName().equals("Jwttoken")) { - return cookie.getValue(); - } - } - } - return null; - } - - private void clearUserIdCookie(HttpServletResponse response) { - Cookie cookie = new Cookie("userId", null); - cookie.setPath("/"); - cookie.setHttpOnly(true); - cookie.setSecure(true); - cookie.setMaxAge(0); // Invalidate the cookie - response.addCookie(cookie); - } -} diff --git a/src/main/java/com/iemr/common/utils/JwtUtil.java b/src/main/java/com/iemr/common/utils/JwtUtil.java deleted file mode 100644 index c0241954..00000000 --- a/src/main/java/com/iemr/common/utils/JwtUtil.java +++ /dev/null @@ -1,101 +0,0 @@ -package com.iemr.common.utils; - -import java.util.Date; -import java.util.UUID; -import java.util.function.Function; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; - -import io.jsonwebtoken.Claims; -import io.jsonwebtoken.ExpiredJwtException; -import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.MalformedJwtException; -import io.jsonwebtoken.UnsupportedJwtException; -import io.jsonwebtoken.security.Keys; -import io.jsonwebtoken.security.SignatureException; - -import javax.crypto.SecretKey; - -@Component -public class JwtUtil { - - @Value("${jwt.secret}") - private String SECRET_KEY; - - @Value("${jwt.access.expiration}") - private long ACCESS_EXPIRATION_TIME; - - @Value("${jwt.refresh.expiration}") - private long REFRESH_EXPIRATION_TIME; - - private SecretKey getSigningKey() { - if (SECRET_KEY == null || SECRET_KEY.isEmpty()) { - throw new IllegalStateException("JWT secret key is not set in application.properties"); - } - return Keys.hmacShaKeyFor(SECRET_KEY.getBytes()); - } - - public String generateToken(String username, String userId) { - return buildToken(username, userId, "access", ACCESS_EXPIRATION_TIME); - } - - public String generateRefreshToken(String username, String userId) { - return buildToken(username, userId, "refresh", REFRESH_EXPIRATION_TIME); - } - - private String buildToken(String username, String userId, String tokenType, long expiration) { - return Jwts.builder() - .subject(username) - .claim("userId", userId) - .claim("token_type", tokenType) - .id(UUID.randomUUID().toString()) - .issuedAt(new Date()) - .expiration(new Date(System.currentTimeMillis() + expiration)) - .signWith(getSigningKey()) - .compact(); - } - - public Claims validateToken(String token) { - try { - return Jwts.parser() - .verifyWith(getSigningKey()) - .build() - .parseSignedClaims(token) - .getPayload(); - - } catch (ExpiredJwtException ex) { - // Handle expired token specifically if needed - } catch (UnsupportedJwtException | MalformedJwtException | SignatureException | IllegalArgumentException ex) { - // Log specific error types - } - return null; - } - - public T getClaimFromToken(String token, Function claimsResolver) { - final Claims claims = getAllClaimsFromToken(token); - return claimsResolver.apply(claims); - } - - public Claims getAllClaimsFromToken(String token) { - return Jwts.parser() - .verifyWith(getSigningKey()) - .build() - .parseSignedClaims(token) - .getPayload(); - } - - - public long getRefreshTokenExpiration() { - return REFRESH_EXPIRATION_TIME; - } - - // Additional helper methods - public String getJtiFromToken(String token) { - return getAllClaimsFromToken(token).getId(); - } - - public String getUsernameFromToken(String token) { - return getAllClaimsFromToken(token).getSubject(); - } -} \ No newline at end of file