-
Notifications
You must be signed in to change notification settings - Fork 32
Jwt api implementation #62
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughThe pull request introduces a comprehensive JWT (JSON Web Token) authentication mechanism for the Admin-API project. The changes include adding JWT dependencies, configuring JWT-related properties across different environments, and implementing utility classes for JWT token generation, validation, and management. The implementation involves creating several new utility classes like Changes
Suggested reviewers
Poem
Tip π Web search-backed reviews and chat
π Recent review detailsConfiguration used: CodeRabbit UI π Files selected for processing (1)
β Files skipped from review due to trivial changes (1)
β° Context from checks skipped due to timeout of 90000ms (1)
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? πͺ§ TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 17
π§Ή Outside diff range and nitpick comments (7)
src/main/java/com/iemr/admin/utils/JwtUserIdValidationFilter.java (1)
87-87: Enhancement: Catch Specific Exceptions Instead of GeneralExceptionCatching the general
Exceptionclass can obscure the root cause of errors and make debugging more difficult. It's better to catch specific exceptions that you expect might occur.Consider modifying the catch block to handle specific exceptions, such as
IOException,ServletException, or any custom exceptions thrown byvalidateUserIdAndJwtTokenmethod.src/main/java/com/iemr/admin/utils/JwtUtil.java (2)
29-29: Specify character encoding when convertingSECRET_KEYto bytesWhen converting
SECRET_KEYto bytes, it's advisable to specify the character encoding to ensure consistent behavior across different platforms. For example:- return Keys.hmacShaKeyFor(SECRET_KEY.getBytes()); + return Keys.hmacShaKeyFor(SECRET_KEY.getBytes(StandardCharsets.UTF_8));
71-76: Handle exceptions consistently inextractAllClaimsmethodThe
extractAllClaimsmethod does not handle exceptions that may occur during token parsing. Consider adding exception handling similar to thevalidateTokenmethod to ensure consistent error handling throughout the class.Suggested change:
private Claims extractAllClaims(String token) { try { return Jwts.parserBuilder() .setSigningKey(getSigningKey()) .build() .parseClaimsJws(token) .getBody(); } catch (Exception e) { + throw new JwtValidationException("Invalid JWT token", e); } }src/main/java/com/iemr/admin/utils/CookieUtil.java (2)
15-25: Add logging for security eventsConsider adding debug logging for cookie operations to aid in troubleshooting and security monitoring.
+import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + @Service public class CookieUtil { + private static final Logger logger = LoggerFactory.getLogger(CookieUtil.class); + public Optional<String> getCookieValue(HttpServletRequest request, String cookieName) { + logger.debug("Attempting to retrieve cookie: {}", cookieName); Cookie[] cookies = request.getCookies(); if (cookies != null) { for (Cookie cookie : cookies) { if (cookieName.equals(cookie.getName())) { + logger.debug("Found cookie: {}", cookieName); return Optional.of(cookie.getValue()); } } } + logger.debug("Cookie not found: {}", cookieName); return Optional.empty(); }
1-44: Consider adding unit testsThe cookie utility class handles security-sensitive operations and should be thoroughly tested.
Would you like me to help generate comprehensive unit tests for this class? The tests should cover:
- Cookie retrieval with null/empty cookies
- Cookie security attributes
- Token management scenarios
pom.xml (2)
67-70: Consider updating logback-ecs-encoder versionThe current version (1.3.2) is stable but outdated. Consider upgrading to version 1.5.0 for the latest features and security fixes.
<dependency> <groupId>co.elastic.logging</groupId> <artifactId>logback-ecs-encoder</artifactId> - <version>1.3.2</version> + <version>1.5.0</version> </dependency>
Line range hint
242-253: Critical: Avoid using release candidate versions in productionUsing Jackson RC versions (2.17.0-rc1) in production is risky as they may contain unstable features. Since you're using Spring Boot 3.2.2 as parent, it's recommended to:
- Remove explicit Jackson dependencies and use the versions managed by Spring Boot
- If specific version is needed, use the latest stable version (2.16.1)
-<dependency> - <groupId>com.fasterxml.jackson.core</groupId> - <artifactId>jackson-databind</artifactId> - <version>2.17.0-rc1</version> -</dependency> - -<dependency> - <groupId>com.fasterxml.jackson.core</groupId> - <artifactId>jackson-core</artifactId> - <version>2.17.0-rc1</version> -</dependency>
π Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
π Files selected for processing (13)
pom.xml(7 hunks)src/main/environment/admin_ci.properties(1 hunks)src/main/environment/admin_dev.properties(1 hunks)src/main/environment/admin_example.properties(1 hunks)src/main/environment/admin_test.properties(1 hunks)src/main/environment/admin_uat.properties(1 hunks)src/main/java/com/iemr/admin/repository/user/UserLoginRepo.java(1 hunks)src/main/java/com/iemr/admin/utils/CookieUtil.java(1 hunks)src/main/java/com/iemr/admin/utils/FilterConfig.java(1 hunks)src/main/java/com/iemr/admin/utils/JwtAuthenticationUtil.java(1 hunks)src/main/java/com/iemr/admin/utils/JwtUserIdValidationFilter.java(1 hunks)src/main/java/com/iemr/admin/utils/JwtUtil.java(1 hunks)src/main/resources/application.properties(0 hunks)
π€ Files with no reviewable changes (1)
- src/main/resources/application.properties
π Additional comments (6)
src/main/java/com/iemr/admin/repository/user/UserLoginRepo.java (2)
1-9: LGTM!
Package structure and imports are clean and appropriate.
14-15: π οΈ Refactor suggestion
Consider adding index hint and Optional return type
The query implementation could be improved for better security and maintainability:
- Consider returning
Optional<M_User>to handle the case when user is not found:
-public M_User getUserByUserID(@Param("userID") Long userID);
+public Optional<M_User> getUserByUserID(@Param("userID") Long userID);-
Ensure the
userIDcolumn is properly indexed for query performance. -
Consider adding method-level security using
@PreAuthorizeto prevent unauthorized access.
Let's verify the database schema and security configuration:
src/main/java/com/iemr/admin/utils/JwtUserIdValidationFilter.java (1)
58-60: Verify the Use of equalsIgnoreCase for Path Comparison
Using equalsIgnoreCase for URL path comparison may lead to unintended bypasses of security checks, as URL paths are case-sensitive. This can introduce security risks if not handled properly.
Please confirm whether case-insensitive comparison is intentional and appropriate for the endpoint /user/logOutUserFromConcurrentSession. If case sensitivity is required, consider using equals instead.
src/main/java/com/iemr/admin/utils/FilterConfig.java (1)
12-17: LGTM: Filter Registration Implemented Correctly
The filter registration for JwtUserIdValidationFilter is correctly implemented, and the filter will apply to all API endpoints as intended.
pom.xml (2)
254-273: LGTM: JWT dependencies are properly configured
The JWT implementation uses appropriate dependencies with correct runtime scopes for implementation modules.
Line range hint 385-389: LGTM: Build configuration changes are appropriate
The maven-antrun-plugin configuration for property file concatenation is correctly implemented.
src/main/java/com/iemr/admin/utils/JwtUserIdValidationFilter.java
Outdated
Show resolved
Hide resolved
src/main/java/com/iemr/admin/utils/JwtUserIdValidationFilter.java
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
π Outside diff range comments (1)
pom.xml (1)
Line range hint
242-253: Avoid using Release Candidate versions in productionThe Jackson dependencies are using version 2.17.0-rc1 which is a Release Candidate. This could introduce instability in production.
Consider using the latest stable version:
-<version>2.17.0-rc1</version> +<version>2.16.1</version>
β»οΈ Duplicate comments (3)
src/main/java/com/iemr/admin/utils/CookieUtil.java (1)
26-29:β οΈ Potential issueFix potential NullPointerException in getJwtTokenFromCookie
The method assumes cookies array is non-null, which could lead to NPE.
Apply this fix:
public String getJwtTokenFromCookie(HttpServletRequest request) { + Cookie[] cookies = request.getCookies(); + if (cookies == null) { + return null; + } - return Arrays.stream(request.getCookies()) + return Arrays.stream(cookies) .filter(cookie -> "Jwttoken".equals(cookie.getName())) .map(Cookie::getValue) .findFirst() .orElse(null); }pom.xml (1)
254-273:β οΈ Potential issueAdd Spring Security dependency for JWT implementation
For a robust JWT implementation, it's recommended to add Spring Security.
src/main/java/com/iemr/admin/utils/JwtAuthenticationUtil.java (1)
22-33: π οΈ Refactor suggestionChoose a consistent dependency injection approach
The class mixes field injection with constructor injection, and the RedisTemplate is not included in the constructor.
π§Ή Nitpick comments (4)
src/main/java/com/iemr/admin/utils/CookieUtil.java (1)
14-24: Consider using Optional.ofNullable for null safetyThe null check can be simplified using Optional.ofNullable for better readability and null safety.
public Optional<String> 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(); + return Optional.ofNullable(request.getCookies()) + .flatMap(cookies -> Arrays.stream(cookies) + .filter(cookie -> cookieName.equals(cookie.getName())) + .findFirst() + .map(Cookie::getValue)); }src/main/java/com/iemr/admin/utils/JwtUtil.java (1)
31-40: Consider configurable token expiration timeThe token expiration time is hardcoded to 1 day. Consider making it configurable through properties.
@Component public class JwtUtil { + @Value("${jwt.token.expiration:86400000}") + private long tokenExpiration; - private static final long EXPIRATION_TIME = 24L * 60 * 60 * 1000; // 1 day in milliseconds public String generateToken(String username, String userId) { Date now = new Date(); - Date expiryDate = new Date(now.getTime() + EXPIRATION_TIME); + Date expiryDate = new Date(now.getTime() + tokenExpiration);src/main/java/com/iemr/admin/utils/JwtAuthenticationUtil.java (2)
86-97: Enhance cache retrieval error handlingThe method logs warnings but doesn't provide detailed error information for debugging.
Consider enhancing the error handling:
private M_User getUserFromCache(String userId) { String redisKey = "user_" + userId; try { M_User user = (M_User) redisTemplate.opsForValue().get(redisKey); if (user == null) { - logger.warn("User not found in Redis."); + logger.warn("User not found in Redis for userId: {}", userId); } else { - logger.info("User fetched successfully from Redis."); + logger.debug("User fetched successfully from Redis for userId: {}", userId); } return user; + } catch (Exception e) { + logger.error("Error fetching user from Redis for userId: {}", userId, e); + return null; } }
62-84: Add rate limiting for token validationThe token validation endpoint could be susceptible to brute force attacks.
Consider implementing rate limiting using Redis:
- Track validation attempts per IP/user
- Implement exponential backoff for failed attempts
- Add appropriate headers (X-RateLimit-*) in responses
Would you like me to provide a detailed implementation for rate limiting?
π Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
π Files selected for processing (14)
bin/.gitignore(1 hunks)pom.xml(7 hunks)src/main/environment/admin_ci.properties(1 hunks)src/main/environment/admin_dev.properties(1 hunks)src/main/environment/admin_example.properties(1 hunks)src/main/environment/admin_test.properties(1 hunks)src/main/environment/admin_uat.properties(1 hunks)src/main/java/com/iemr/admin/RoleMasterApplication.java(2 hunks)src/main/java/com/iemr/admin/config/RedisConfig.java(1 hunks)src/main/java/com/iemr/admin/utils/CookieUtil.java(1 hunks)src/main/java/com/iemr/admin/utils/FilterConfig.java(1 hunks)src/main/java/com/iemr/admin/utils/JwtAuthenticationUtil.java(1 hunks)src/main/java/com/iemr/admin/utils/JwtUserIdValidationFilter.java(1 hunks)src/main/java/com/iemr/admin/utils/JwtUtil.java(1 hunks)
β Files skipped from review due to trivial changes (1)
- bin/.gitignore
π§ Files skipped from review as they are similar to previous changes (7)
- src/main/environment/admin_uat.properties
- src/main/environment/admin_test.properties
- src/main/environment/admin_dev.properties
- src/main/environment/admin_example.properties
- src/main/environment/admin_ci.properties
- src/main/java/com/iemr/admin/utils/FilterConfig.java
- src/main/java/com/iemr/admin/utils/JwtUserIdValidationFilter.java
π Additional comments (2)
src/main/java/com/iemr/admin/utils/JwtUtil.java (2)
43-49:
Improve error handling in validateToken
Returning null on validation failure can lead to NPEs. Consider throwing a custom exception.
+public class JwtValidationException extends RuntimeException {
+ public JwtValidationException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
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
+ throw new JwtValidationException("Invalid JWT token", e);
}
}Likely invalid or redundant comment.
24-29:
Strengthen SECRET_KEY validation and cache signing key
Current implementation has two issues:
- The SECRET_KEY validation should check for minimum length and complexity
- The signing key is regenerated for each request
@Component
public class JwtUtil {
+ private Key signingKey;
+
+ @PostConstruct
+ public void init() {
+ if (SECRET_KEY == null || SECRET_KEY.length() < 32) {
+ throw new IllegalStateException("JWT secret key must be at least 32 characters long");
+ }
+ this.signingKey = Keys.hmacShaKeyFor(SECRET_KEY.getBytes());
+ }
+
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());
+ return signingKey;
}Likely invalid or redundant comment.
|
|
ravishanigarapu
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks ok



π Description
JIRA ID:
Please provide a summary of the change and the motivation behind it. Include relevant context and details.
β Type of Change
βΉοΈ Additional Information
Please describe how the changes were tested, and include any relevant screenshots, logs, or other information that provides additional context.
Summary by CodeRabbit
New Features
Bug Fixes
Chores
.gitignorefile to manage ignored files and directories.