diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index bf0f243..3434190 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -26,7 +26,7 @@ jobs: uses: actions/setup-java@v2 with: java-version: 17 - distribution: 'zulu' + distribution: 'adopt' - name: Build with Maven run: mvn clean install -DENV_VAR=${{ env.ENV_VAR }} @@ -35,7 +35,7 @@ jobs: run: mvn -B package --file pom.xml - name: Upload WAR file as artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ECD-API path: target/ecdapi.war diff --git a/pom.xml b/pom.xml index d9a982d..2d0d9fb 100644 --- a/pom.xml +++ b/pom.xml @@ -28,25 +28,21 @@ 1.2.0.Final - + org.springframework.boot spring-boot-starter-aop 3.2.2 - - co.elastic.logging - logback-ecs-encoder - 1.3.2 + + co.elastic.logging + logback-ecs-encoder + 1.3.2 - + org.slf4j slf4j-api @@ -101,8 +97,7 @@ 8.2.0 - + jakarta.persistence jakarta.persistence-api @@ -169,15 +164,14 @@ org.apache.poi poi-ooxml 5.2.5 - - - - - - - - + + + + + + + + org.springframework.boot spring-boot-starter-data-redis @@ -219,8 +213,7 @@ jackson-datatype-joda 2.17.0 - + com.fasterxml.jackson.core jackson-databind @@ -232,6 +225,26 @@ jackson-core 2.17.0-rc1 + + + io.jsonwebtoken + jjwt-api + 0.12.6 + + + + io.jsonwebtoken + jjwt-impl + 0.12.6 + runtime + + + + io.jsonwebtoken + jjwt-jackson + 0.12.6 + runtime + @@ -315,8 +328,7 @@ ${target-properties} and ${source-properties} - diff --git a/src/main/environment/ecd_ci.properties b/src/main/environment/ecd_ci.properties index afc45ca..dfcfdb0 100644 --- a/src/main/environment/ecd_ci.properties +++ b/src/main/environment/ecd_ci.properties @@ -14,10 +14,17 @@ secondary.datasource.driver-class-name=com.mysql.jdbc.Driver registerBeneficiaryUrl=@env.COMMON_API@/beneficiary/create ##Beneficiary Edit Url + +beneficiaryEditUrl =@env.COMMON_API_BASE_URL@/beneficiary/update +jwt.secret=@env.JWT_SECRET_KEY@ + beneficiaryEditUrl =@env.COMMON_API@/beneficiary/update + #ELK logging file name logging.file.name=@env.ECD_API_LOGGING_FILE_NAME@ + springdoc.api-docs.enabled=false -springdoc.swagger-ui.enabled=false \ No newline at end of file +springdoc.swagger-ui.enabled=false + diff --git a/src/main/environment/ecd_dev.properties b/src/main/environment/ecd_dev.properties index e668931..779e08f 100644 --- a/src/main/environment/ecd_dev.properties +++ b/src/main/environment/ecd_dev.properties @@ -16,5 +16,9 @@ registerBeneficiaryUrl=/commonapi-v1.0/beneficia ##Beneficiary Edit Url beneficiaryEditUrl =/commonapi-v1.0/beneficiary/update +jwt.secret= + + springdoc.api-docs.enabled=true -springdoc.swagger-ui.enabled=true \ No newline at end of file +springdoc.swagger-ui.enabled=true + diff --git a/src/main/environment/ecd_test.properties b/src/main/environment/ecd_test.properties index e668931..779e08f 100644 --- a/src/main/environment/ecd_test.properties +++ b/src/main/environment/ecd_test.properties @@ -16,5 +16,9 @@ registerBeneficiaryUrl=/commonapi-v1.0/beneficia ##Beneficiary Edit Url beneficiaryEditUrl =/commonapi-v1.0/beneficiary/update +jwt.secret= + + springdoc.api-docs.enabled=true -springdoc.swagger-ui.enabled=true \ No newline at end of file +springdoc.swagger-ui.enabled=true + diff --git a/src/main/environment/ecd_uat.properties b/src/main/environment/ecd_uat.properties index e668931..779e08f 100644 --- a/src/main/environment/ecd_uat.properties +++ b/src/main/environment/ecd_uat.properties @@ -16,5 +16,9 @@ registerBeneficiaryUrl=/commonapi-v1.0/beneficia ##Beneficiary Edit Url beneficiaryEditUrl =/commonapi-v1.0/beneficiary/update +jwt.secret= + + springdoc.api-docs.enabled=true -springdoc.swagger-ui.enabled=true \ No newline at end of file +springdoc.swagger-ui.enabled=true + diff --git a/src/main/java/com/iemr/ecd/EcdApiApplication.java b/src/main/java/com/iemr/ecd/EcdApiApplication.java index fcba632..5a7f6e7 100644 --- a/src/main/java/com/iemr/ecd/EcdApiApplication.java +++ b/src/main/java/com/iemr/ecd/EcdApiApplication.java @@ -24,6 +24,13 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; +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 com.iemr.ecd.dao.Users; import io.swagger.v3.oas.annotations.OpenAPIDefinition; import io.swagger.v3.oas.annotations.info.Contact; @@ -37,4 +44,19 @@ public static void main(String[] args) { SpringApplication.run(EcdApiApplication.class, args); } + @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<>(Users.class); + template.setValueSerializer(serializer); + + return template; + } + } diff --git a/src/main/java/com/iemr/ecd/config/RedisConfig.java b/src/main/java/com/iemr/ecd/config/RedisConfig.java index 22818fa..58cd150 100644 --- a/src/main/java/com/iemr/ecd/config/RedisConfig.java +++ b/src/main/java/com/iemr/ecd/config/RedisConfig.java @@ -22,11 +22,19 @@ package com.iemr.ecd.config; import org.springframework.beans.factory.annotation.Value; +import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +import com.iemr.ecd.dao.Users; @Configuration +@EnableCaching public class RedisConfig { private @Value("${spring.redis.host}") String redisHost; @@ -37,4 +45,19 @@ LettuceConnectionFactory lettuceConnectionFactory() { return new LettuceConnectionFactory(redisHost, redisPort); } + @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<>(Users.class); + template.setValueSerializer(serializer); + + return template; + } + } diff --git a/src/main/java/com/iemr/ecd/dao/Users.java b/src/main/java/com/iemr/ecd/dao/Users.java new file mode 100644 index 0000000..97c9118 --- /dev/null +++ b/src/main/java/com/iemr/ecd/dao/Users.java @@ -0,0 +1,103 @@ +package com.iemr.ecd.dao; + +import java.io.Serializable; +import java.sql.Timestamp; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.google.gson.annotations.Expose; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import lombok.Data; + +@Data +@Entity +@Table(name = "m_user") +@JsonIgnoreProperties(ignoreUnknown = true) +public class Users implements Serializable { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Expose + @Column(name = "UserID") + private Long userID; + @Expose + @Column(name = "TitleID") private Short titleID; + @Expose + @Column(name = "FirstName") + private String firstName; + @Expose + @Column(name = "MiddleName") + private String middleName; + @Expose + @Column(name = "lastName") + private String lastName; + @Expose + @Column(name = "GenderID") + private Short genderID; + @Expose + @Column(name = "MaritalStatusID") + private Short maritalStatusID; + @Expose + @Column(name = "AadhaarNo") + private String aadhaarNo; + @Expose + @Column(name = "PAN") + private String pan; + @Expose + @Column(name = "DOB") + private Timestamp dob; + @Expose + @Column(name = "DOJ") + private Timestamp doj; + @Expose + @Column(name = "QualificationID") + private Integer qualificationID; + @Expose + @Column(name = "UserName") + private String userName; + @Expose + @Column(name = "Password") + private String password; + @Expose + @Column(name = "AgentID") + private String agentID; + @Expose + @Column(name = "AgentPassword") + private String agentPassword; + @Expose + @Column(name = "EmailID") + private String emailID; + @Expose + @Column(name = "StatusID") + private Short statusID; + @Expose + @Column(name = "EmergencyContactPerson") + private String emergencyContactPerson; + @Expose + @Column(name = "EmergencyContactNo") + private String emergencyContactNo; + @Expose + @Column(name = "IsSupervisor") + private Boolean isSupervisor; + @Expose + @Column(name = "Deleted") + private Boolean deleted; + @Expose + @Column(name = "CreatedBy") + private String createdBy; + @Expose + @Column(name = "CreatedDate") + private Timestamp createdDate; + @Expose + @Column(name = "ModifiedBy") + private String modifiedBy; + @Expose + @Column(name = "LastModDate") + private Timestamp lastModDate; + +} + diff --git a/src/main/java/com/iemr/ecd/repository/ecd/UserLoginRepo.java b/src/main/java/com/iemr/ecd/repository/ecd/UserLoginRepo.java new file mode 100644 index 0000000..bae8d1e --- /dev/null +++ b/src/main/java/com/iemr/ecd/repository/ecd/UserLoginRepo.java @@ -0,0 +1,16 @@ +package com.iemr.ecd.repository.ecd; + +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.CrudRepository; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +import com.iemr.ecd.dao.Users; + +@Repository +public interface UserLoginRepo extends CrudRepository { + + @Query(" SELECT u FROM Users u WHERE u.userID = :userID AND u.deleted = false ") + public Users getUserByUserID(@Param("userID") Long userID); + +} diff --git a/src/main/java/com/iemr/ecd/utils/mapper/CookieUtil.java b/src/main/java/com/iemr/ecd/utils/mapper/CookieUtil.java new file mode 100644 index 0000000..d0c24c1 --- /dev/null +++ b/src/main/java/com/iemr/ecd/utils/mapper/CookieUtil.java @@ -0,0 +1,31 @@ +package com.iemr.ecd.utils.mapper; + +import java.util.Arrays; +import java.util.Optional; + +import org.springframework.stereotype.Service; + +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +@Service +public class CookieUtil { + + 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 String getJwtTokenFromCookie(HttpServletRequest request) { + 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/ecd/utils/mapper/FilterConfig.java b/src/main/java/com/iemr/ecd/utils/mapper/FilterConfig.java new file mode 100644 index 0000000..98867f8 --- /dev/null +++ b/src/main/java/com/iemr/ecd/utils/mapper/FilterConfig.java @@ -0,0 +1,19 @@ +package com.iemr.ecd.utils.mapper; + +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/ecd/utils/mapper/JwtAuthenticationUtil.java b/src/main/java/com/iemr/ecd/utils/mapper/JwtAuthenticationUtil.java new file mode 100644 index 0000000..e72b50a --- /dev/null +++ b/src/main/java/com/iemr/ecd/utils/mapper/JwtAuthenticationUtil.java @@ -0,0 +1,126 @@ +package com.iemr.ecd.utils.mapper; + +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.ecd.dao.Users; +import com.iemr.ecd.repository.ecd.UserLoginRepo; +import com.iemr.ecd.utils.advice.exception_handler.ECDException; + +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 UserLoginRepo userLoginRepo; + private final Logger logger = LoggerFactory.getLogger(this.getClass().getName()); + + 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 Exception { + try { + // Validate JWT token and extract claims + Claims claims = jwtUtil.validateToken(jwtToken); + + if (claims == null) { + throw new ECDException("Invalid JWT token."); + } + + String userId = claims.get("userId", String.class); + + // Check if user data is present in Redis + Users 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 Exception("Invalid User ID."); + } + + return true; // Valid userId and JWT token + } catch (Exception e) { + logger.error("Validation failed: " + e.getMessage(), e); + throw new Exception("Validation error: " + e.getMessage(), e); + } + } + + private Users getUserFromCache(String userId) { + String redisKey = "user_" + userId; // The Redis key format + Users user = (Users) 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 Users 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 + Users user = userLoginRepo.getUserByUserID(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/ecd/utils/mapper/JwtUserIdValidationFilter.java b/src/main/java/com/iemr/ecd/utils/mapper/JwtUserIdValidationFilter.java new file mode 100644 index 0000000..d7d1c09 --- /dev/null +++ b/src/main/java/com/iemr/ecd/utils/mapper/JwtUserIdValidationFilter.java @@ -0,0 +1,111 @@ +package com.iemr.ecd.utils.mapper; + +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 login and public endpoints + if (path.equals(contextPath + "/user/userAuthenticate") + || path.equalsIgnoreCase(contextPath + "/user/logOutUserFromConcurrentSession") + || path.startsWith(contextPath + "/public")) { + 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) { + response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "JWT token not found in cookies or headers"); + return; + } + + // Validate JWT token and userId + boolean isValid = jwtAuthenticationUtil.validateUserIdAndJwtToken(jwtToken); + + if (isValid) { + // If token is valid, allow the request to proceed + filterChain.doFilter(servletRequest, servletResponse); + } else { + 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 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/ecd/utils/mapper/JwtUtil.java b/src/main/java/com/iemr/ecd/utils/mapper/JwtUtil.java new file mode 100644 index 0000000..18630d8 --- /dev/null +++ b/src/main/java/com/iemr/ecd/utils/mapper/JwtUtil.java @@ -0,0 +1,63 @@ +package com.iemr.ecd.utils.mapper; + +import java.security.Key; +import java.util.Date; +import java.util.function.Function; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import io.jsonwebtoken.security.Keys; + +@Component +public class JwtUtil { + + @Value("${jwt.secret}") + private String SECRET_KEY; + + private static final long EXPIRATION_TIME = 24L * 60 * 60 * 1000; // 1 day in milliseconds + + // Generate a key using the secret + private Key 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()); + } + + // Generate JWT Token + public String generateToken(String username, String userId) { + Date now = new Date(); + Date expiryDate = new Date(now.getTime() + EXPIRATION_TIME); + + // Include the userId in the JWT claims + return Jwts.builder().setSubject(username).claim("userId", userId) // Add userId as a claim + .setIssuedAt(now).setExpiration(expiryDate).signWith(getSigningKey(), SignatureAlgorithm.HS256) + .compact(); + } + + // Validate and parse JWT Token + public Claims validateToken(String token) { + try { + return Jwts.parser().setSigningKey(getSigningKey()).build().parseClaimsJws(token).getBody(); + } catch (Exception e) { + return null; // Handle token parsing/validation errors + } + } + + public String extractUsername(String token) { + return extractClaim(token, Claims::getSubject); + } + + public T extractClaim(String token, Function claimsResolver) { + final Claims claims = extractAllClaims(token); + return claimsResolver.apply(claims); + } + + private Claims extractAllClaims(String token) { + return Jwts.parser().setSigningKey(getSigningKey()).build().parseClaimsJws(token).getBody(); + } +}