Skip to content

Conversation

@vishwab1
Copy link
Member

@vishwab1 vishwab1 commented May 26, 2025

πŸ“‹ Description

JIRA ID:

Please provide a summary of the change and the motivation behind it. Include relevant context and details.


βœ… Type of Change

  • 🐞 Bug fix (non-breaking change which resolves an issue)
  • ✨ New feature (non-breaking change which adds functionality)
  • πŸ”₯ Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • πŸ›  Refactor (change that is neither a fix nor a new feature)
  • βš™οΈ Config change (configuration file or build script updates)
  • πŸ“š Documentation (updates to docs or readme)
  • πŸ§ͺ Tests (adding new or updating existing tests)
  • 🎨 UI/UX (changes that affect the user interface)
  • πŸš€ Performance (improves performance)
  • 🧹 Chore (miscellaneous changes that don't modify src or test files)

ℹ️ 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

    • Added support for JSON processing and JWT authentication, enabling secure token handling and user validation.
    • Introduced new configuration options for Cross-Origin Resource Sharing (CORS) and logging file names.
    • Implemented centralized and dynamic CORS configuration, allowing flexible control over allowed origins.
    • Added new user entity and repository for enhanced user management.
    • Introduced utility classes for JWT and cookie management.
  • Refactor

    • Centralized CORS handling by removing individual CORS annotations from controllers.

@coderabbitai
Copy link

coderabbitai bot commented May 26, 2025

Walkthrough

This change introduces centralized and dynamic CORS handling, JWT authentication, and user validation features. It adds new configuration properties for CORS and logging, removes @CrossOrigin annotations from controllers, and implements utility classes for JWT management, CORS filtering, and user repository access. Several new Maven dependencies are included for JSON and JWT support.

Changes

File(s) Change Summary
pom.xml Added dependencies for Jersey JSON processing, JAXB runtime, and JJWT libraries for JWT handling.
src/main/environment/1097_ci.properties
.../common_ci.properties
Added logging.file.name and cors.allowed-origins properties referencing environment variables.
src/main/environment/1097_example.properties
.../common_example.properties
Added cors.allowed-origins property (empty or wildcard) to example configs.
src/main/java/com/iemr/common/identity/config/CorsConfig.java New Spring config class for dynamic CORS using application property for allowed origins.
src/main/java/com/iemr/common/identity/controller/IdentityController.java
.../VersionController.java
.../familyTagging/FamilyTaggingController.java
Removed all @CrossOrigin annotations from REST controllers and their methods.
src/main/java/com/iemr/common/identity/domain/iemr/M_User.java New JPA entity class representing users, with fields mapped to the m_User table.
src/main/java/com/iemr/common/identity/repo/iemr/EmployeeMasterRepo.java New Spring Data repository for M_User entity with user lookup methods.
src/main/java/com/iemr/common/identity/utils/CookieUtil.java New utility class for reading, writing, and extracting JWT tokens from cookies.
src/main/java/com/iemr/common/identity/utils/DynamicCorsFilter.java New filter for setting CORS headers dynamically based on allowed origins.
src/main/java/com/iemr/common/identity/utils/FilterConfig.java New Spring config for registering JWT user ID validation filter.
src/main/java/com/iemr/common/identity/utils/JwtAuthenticationUtil.java New utility for validating JWT tokens and user IDs, integrating Redis and DB lookups.
src/main/java/com/iemr/common/identity/utils/JwtUserIdValidationFilter.java New servlet filter for JWT and user ID validation, handling CORS and preflight requests.
src/main/java/com/iemr/common/identity/utils/JwtUtil.java New utility for JWT token generation, validation, and claim extraction.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Filter as JwtUserIdValidationFilter
    participant JwtAuthUtil as JwtAuthenticationUtil
    participant CookieUtil
    participant JwtUtil
    participant Redis
    participant DB as EmployeeMasterRepo

    Client->>Filter: HTTP Request (with Jwttoken cookie/header)
    Filter->>CookieUtil: getJwtTokenFromCookie(request)
    CookieUtil-->>Filter: JWT token (if present)
    alt Login/Logout/Public endpoint
        Filter-->>Client: Proceed without JWT validation
    else
        Filter->>JwtAuthUtil: validateUserIdAndJwtToken(jwtToken)
        JwtAuthUtil->>JwtUtil: validateToken(jwtToken)
        JwtUtil-->>JwtAuthUtil: Claims or error
        JwtAuthUtil->>Redis: get(userId)
        alt User in Redis
            Redis-->>JwtAuthUtil: User data
        else User not in Redis
            JwtAuthUtil->>DB: findByUserID(userId)
            DB-->>JwtAuthUtil: User data
            JwtAuthUtil->>Redis: set(userId, user data)
        end
        alt Valid user
            JwtAuthUtil-->>Filter: true
            Filter-->>Client: Proceed to controller
        else Invalid
            JwtAuthUtil-->>Filter: false
            Filter-->>Client: 401 Unauthorized
        end
    end
Loading

Possibly related PRs

Poem

A hop, a leap, and code anewβ€”
CORS now dances, dynamic and true.
JWTs are checked with careful might,
Cookies and claims in the moonlight.
Controllers lighter, configs grown,
Security’s garden, freshly sown!
πŸ₯•βœ¨

✨ Finishing Touches
  • πŸ“ Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❀️ Share
πŸͺ§ Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@sonarqubecloud
Copy link

Quality Gate Failed Quality Gate failed

Failed conditions
4.2% Duplication on New Code (required ≀ 3%)

See analysis details on SonarQube Cloud

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 26

πŸ”­ Outside diff range comments (1)
src/main/java/com/iemr/common/identity/controller/IdentityController.java (1)

1-1001: πŸ› οΈ Refactor suggestion

Consider refactoring to address file length and maintainability issues.

The file exceeds the maximum allowed length (1001 lines vs 500). Consider breaking this controller into smaller, more focused controllers or extracting common functionality into service methods.

Potential refactoring approaches:

  1. Split by functionality: Create separate controllers for different concern areas (search, create/edit, image handling, etc.)
  2. Extract helper methods: Move response building logic to utility classes
  3. Reduce parameter documentation: The extensive @Param documentation could be moved to OpenAPI annotations

This will improve:

  • Code maintainability and readability
  • Test coverage and debugging
  • Team collaboration and code reviews
  • Compliance with coding standards

Would you like me to help design a refactoring strategy for this controller?

🧰 Tools
πŸͺ› GitHub Actions: Build and Static Code Analysis On Pull Request

[warning] 1-1001: File length exceeds maximum allowed (1001 lines vs 500). Multiple style warnings including line length violations, 'if' and 'else' constructs missing braces, and 'package' separation.

πŸͺ› GitHub Actions: CodeQL

[warning] 1-1001: File length exceeds maximum allowed (1001 lines). Multiple Checkstyle warnings including 'package' separation, line length violations, 'if' constructs missing braces, and whitespace issues.

🧹 Nitpick comments (5)
src/main/java/com/iemr/common/identity/domain/iemr/M_User.java (1)

132-140: Remove TODO comments and improve constructor implementation.

The constructors contain TODO comments that should be removed, and the parameterized constructor could be more robust.

     public M_User() {
-        // TODO Auto-generated constructor stub
     }

     public M_User(Integer userID, String userName) {
-        // TODO Auto-generated constructor stub
         this.userID = userID;
         this.userName = userName;
     }
src/main/java/com/iemr/common/identity/utils/JwtAuthenticationUtil.java (1)

105-123: Potential race condition in cache-then-DB pattern.

The current implementation could result in multiple database calls if concurrent requests for the same user occur when the user is not in cache.

Consider using Redis distributed locking or Spring's @Cacheable annotation to prevent race conditions:

@Cacheable(value = "users", key = "#userId", unless = "#result == null")
private M_User fetchUserFromDB(String userId) {
    return userLoginRepo.getUserByUserID(Integer.parseInt(userId));
}

This would require adding Spring Cache configuration but provides better concurrency handling.

src/main/java/com/iemr/common/identity/utils/JwtUserIdValidationFilter.java (1)

44-50: Consider potential conflicts with Spring CORS configuration.

Manual CORS handling in a filter might conflict with other CORS configurations like @CrossOrigin or CorsConfig.

Consider whether this manual CORS handling is necessary if you already have a dedicated CorsConfig class. Having multiple CORS configurations can lead to unpredictable behavior. You might want to centralize all CORS handling in one place.

src/main/java/com/iemr/common/identity/utils/JwtUtil.java (2)

24-29: Consider caching the signing key for better performance.

The method correctly validates the secret key, but regenerates it on every call.

Consider caching the key since it doesn't change during runtime:

+    private Key cachedSigningKey;
+
     private Key getSigningKey() {
-        if (SECRET_KEY == null || SECRET_KEY.isEmpty()) {
+        if (cachedSigningKey == null) {
+            if (secretKey == null || secretKey.isEmpty()) {
+                throw new IllegalStateException("JWT secret key is not set in application.properties");
+            }
+            cachedSigningKey = Keys.hmacShaKeyFor(secretKey.getBytes());
+        }
+        return cachedSigningKey;
-            throw new IllegalStateException("JWT secret key is not set in application.properties");
-        }
-        return Keys.hmacShaKeyFor(SECRET_KEY.getBytes());
     }

Note: This also requires updating the field reference after fixing the naming convention.


15-85: Add comprehensive documentation and consider security enhancements.

The class lacks JavaDoc documentation and could benefit from additional security measures.

Consider adding comprehensive documentation:

+/**
+ * Utility class for JWT token operations including generation, validation, and claim extraction.
+ * Uses HS256 algorithm with configurable secret key and 24-hour expiration.
+ * 
+ * @author [Author Name]
+ * @version 1.0
+ */
 @Component
 public class JwtUtil {

Also consider these security enhancements:

  • Add token blacklisting mechanism for logout functionality
  • Implement token refresh capability
  • Add audit logging for token operations
  • Consider using RSA256 instead of HS256 for better security in distributed systems

For production use, consider:

  • Storing JWT secrets in a secure vault (AWS Secrets Manager, HashiCorp Vault)
  • Implementing shorter token expiration with refresh tokens
  • Adding rate limiting for token generation endpoints
  • Including additional claims like roles/permissions for authorization
🧰 Tools
πŸͺ› GitHub Actions: Package

[warning] 19-19: Member name 'SECRET_KEY' does not match naming pattern.

πŸͺ› GitHub Actions: CodeQL

[warning] 19-19: Member name 'SECRET_KEY' does not match naming pattern.

πŸ“œ Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between ff29656 and ced3d76.

πŸ“’ Files selected for processing (17)
  • pom.xml (1 hunks)
  • src/main/environment/1097_ci.properties (1 hunks)
  • src/main/environment/1097_example.properties (1 hunks)
  • src/main/environment/common_ci.properties (1 hunks)
  • src/main/environment/common_example.properties (1 hunks)
  • src/main/java/com/iemr/common/identity/config/CorsConfig.java (1 hunks)
  • src/main/java/com/iemr/common/identity/controller/IdentityController.java (21 hunks)
  • src/main/java/com/iemr/common/identity/controller/familyTagging/FamilyTaggingController.java (6 hunks)
  • src/main/java/com/iemr/common/identity/controller/version/VersionController.java (1 hunks)
  • src/main/java/com/iemr/common/identity/domain/iemr/M_User.java (1 hunks)
  • src/main/java/com/iemr/common/identity/repo/iemr/EmployeeMasterRepo.java (1 hunks)
  • src/main/java/com/iemr/common/identity/utils/CookieUtil.java (1 hunks)
  • src/main/java/com/iemr/common/identity/utils/DynamicCorsFilter.java (1 hunks)
  • src/main/java/com/iemr/common/identity/utils/FilterConfig.java (1 hunks)
  • src/main/java/com/iemr/common/identity/utils/JwtAuthenticationUtil.java (1 hunks)
  • src/main/java/com/iemr/common/identity/utils/JwtUserIdValidationFilter.java (1 hunks)
  • src/main/java/com/iemr/common/identity/utils/JwtUtil.java (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
src/main/java/com/iemr/common/identity/config/CorsConfig.java (1)
src/main/java/com/iemr/common/identity/utils/FilterConfig.java (1)
  • Configuration (7-25)
src/main/java/com/iemr/common/identity/utils/FilterConfig.java (1)
src/main/java/com/iemr/common/identity/config/CorsConfig.java (1)
  • Configuration (8-25)
src/main/java/com/iemr/common/identity/utils/JwtUtil.java (2)
src/main/java/com/iemr/common/identity/utils/JwtUserIdValidationFilter.java (1)
  • Component (20-141)
src/main/java/com/iemr/common/identity/utils/JwtAuthenticationUtil.java (1)
  • Component (19-124)
πŸͺ› GitHub Actions: Build and Static Code Analysis On Pull Request
src/main/java/com/iemr/common/identity/controller/IdentityController.java

[warning] 1-1001: File length exceeds maximum allowed (1001 lines vs 500). Multiple style warnings including line length violations, 'if' and 'else' constructs missing braces, and 'package' separation.

src/main/java/com/iemr/common/identity/utils/FilterConfig.java

[error] 10-10: Compilation error: cannot find symbol 'class Value' in FilterConfig.java at line 10.

src/main/java/com/iemr/common/identity/utils/JwtUserIdValidationFilter.java

[warning] 24-48: Method doFilter length exceeds maximum allowed (74 lines vs 50). Line length violation at line 48.

πŸͺ› GitHub Actions: CodeQL
src/main/java/com/iemr/common/identity/controller/IdentityController.java

[warning] 1-1001: File length exceeds maximum allowed (1001 lines). Multiple Checkstyle warnings including 'package' separation, line length violations, 'if' constructs missing braces, and whitespace issues.

src/main/java/com/iemr/common/identity/config/CorsConfig.java

[warning] 23-23: ';' is preceded with whitespace.

src/main/java/com/iemr/common/identity/utils/FilterConfig.java

[error] 10-10: Compilation error: cannot find symbol 'class Value' in FilterConfig.java

src/main/java/com/iemr/common/identity/utils/JwtUtil.java

[warning] 19-19: Member name 'SECRET_KEY' does not match naming pattern.

πŸͺ› GitHub Actions: Package
src/main/java/com/iemr/common/identity/config/CorsConfig.java

[warning] 23-23: Checkstyle warning: ';' is preceded with whitespace.

src/main/java/com/iemr/common/identity/utils/FilterConfig.java

[error] 10-10: Compilation error: cannot find symbol 'class Value' in FilterConfig.java

src/main/java/com/iemr/common/identity/utils/JwtAuthenticationUtil.java

[warning] 24-30: 'VARIABLE_DEF' should be separated from previous line.

src/main/java/com/iemr/common/identity/utils/CookieUtil.java

[warning] 25-25: Parameter name 'Jwttoken' does not match naming pattern.

src/main/java/com/iemr/common/identity/utils/JwtUtil.java

[warning] 19-19: Member name 'SECRET_KEY' does not match naming pattern.

πŸͺ› GitHub Actions: Call Checkstyle
src/main/java/com/iemr/common/identity/utils/FilterConfig.java

[error] 10-10: Compilation error: cannot find symbol 'class Value' in FilterConfig.java at line 10.

πŸͺ› ast-grep (0.38.1)
src/main/java/com/iemr/common/identity/utils/CookieUtil.java

[warning] 33-33: The application does not appear to verify inbound requests which can lead to a Cross-site request forgery (CSRF) vulnerability. If the application uses cookie-based authentication, an attacker can trick users into sending authenticated HTTP requests without their knowledge from any arbitrary domain they visit. To prevent this vulnerability start by identifying if the framework or library leveraged has built-in features or offers plugins for CSRF protection. CSRF tokens should be unique and securely random. The Synchronizer Token or Double Submit Cookie patterns with defense-in-depth mechanisms such as the sameSite cookie flag can help prevent CSRF. For more information, see: [Cross-site request forgery prevention](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Req\ uest_Forgery_Prevention_Cheat_Sheet.html).
Context: response.addCookie(cookie);
Note: [CWE-352] Cross-Site Request Forgery (CSRF). [REFERENCES]
- https://stackoverflow.com/questions/42717210/samesite-cookie-in-java-application

(cookie-missing-samesite-java)


[warning] 33-33: A cookie was detected without setting the 'secure' flag. The 'secure' flag for cookies prevents the client from transmitting the cookie over insecure channels such as HTTP. Set the 'secure' flag by calling '.setSecure(true);'.
Context: response.addCookie(cookie);
Note: [CWE-614] Sensitive Cookie in HTTPS Session Without 'Secure' Attribute. [REFERENCES]
- https://owasp.org/www-community/controls/SecureCookieAttribute

(cookie-missing-secure-flag-java)

src/main/java/com/iemr/common/identity/utils/JwtUserIdValidationFilter.java

[warning] 138-138: The application does not appear to verify inbound requests which can lead to a Cross-site request forgery (CSRF) vulnerability. If the application uses cookie-based authentication, an attacker can trick users into sending authenticated HTTP requests without their knowledge from any arbitrary domain they visit. To prevent this vulnerability start by identifying if the framework or library leveraged has built-in features or offers plugins for CSRF protection. CSRF tokens should be unique and securely random. The Synchronizer Token or Double Submit Cookie patterns with defense-in-depth mechanisms such as the sameSite cookie flag can help prevent CSRF. For more information, see: [Cross-site request forgery prevention](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Req\ uest_Forgery_Prevention_Cheat_Sheet.html).
Context: response.addCookie(cookie);
Note: [CWE-352] Cross-Site Request Forgery (CSRF). [REFERENCES]
- https://stackoverflow.com/questions/42717210/samesite-cookie-in-java-application

(cookie-missing-samesite-java)

πŸ”‡ Additional comments (12)
src/main/environment/common_ci.properties (1)

23-23: Good use of environment variables for CORS configuration.

Using environment variables for CORS configuration allows for flexible and secure deployment-specific settings without hardcoding values.

src/main/java/com/iemr/common/identity/controller/version/VersionController.java (1)

44-44: LGTM: Supports centralized CORS configuration approach.

The removal of @CrossOrigin annotations (as mentioned in the AI summary) and minimal code changes align well with the centralized CORS management strategy being implemented through configuration classes and filters. This approach provides better maintainability and consistency across the application.

src/main/java/com/iemr/common/identity/controller/familyTagging/FamilyTaggingController.java (1)

38-38:

Details

βœ… Verification successful

LGTM! CORS annotations successfully centralized.

The removal of @CrossOrigin annotations aligns with the PR's objective to implement centralized CORS handling. This is a good architectural improvement that replaces scattered controller-level annotations with unified configuration.

Please verify that the new centralized CORS configuration (CorsConfig and DynamicCorsFilter) properly handles the same origins and HTTP methods that were previously allowed by these removed annotations.

Also applies to: 46-46, 62-62, 78-78, 94-94, 110-110, 126-126


🏁 Script executed:

#!/bin/bash
# Description: Verify that CorsConfig and DynamicCorsFilter are properly configured to handle CORS for family tagging endpoints

# Check if CorsConfig class exists and is properly configured
ast-grep --pattern 'class CorsConfig {
  $$$
}'

# Check if DynamicCorsFilter exists and handles CORS headers
ast-grep --pattern 'class DynamicCorsFilter {
  $$$
}'

# Search for CORS configuration properties
rg -A 3 "cors.allowed-origins"

Length of output: 1962


🏁 Script executed:

#!/bin/bash
# Inspect CorsConfig.java for class definition and mappings
rg -n "class CorsConfig" -A20 src/main/java/com/iemr/common/identity/config/CorsConfig.java
rg -n "addMapping" -A10 src/main/java/com/iemr/common/identity/config/CorsConfig.java
rg -n "allowedMethods" -A5 src/main/java/com/iemr/common/identity/config/CorsConfig.java

# Inspect DynamicCorsFilter.java for filter implementation and header handling
rg -n "class DynamicCorsFilter" -A20 src/main/java/com/iemr/common/identity/utils/DynamicCorsFilter.java
rg -n "Access-Control-Allow" -A5 src/main/java/com/iemr/common/identity/utils/DynamicCorsFilter.java

Length of output: 2959


CORS Configuration Verified

CorsConfig and DynamicCorsFilter are both present and correctly configured:

  • CorsConfig (WebMvcConfigurer) applies to all paths (/**), reads cors.allowed-origins, splits on commas, and allows GET, POST, PUT, DELETE, OPTIONS with all headers, credentials, and a 3600 s max age.
  • DynamicCorsFilter reads the same cors.allowed-origins array and sets the Access-Control-Allow-Origin header for matching origins.

Controller-level @CrossOrigin annotations can be safely removed in favor of this centralized setup. No further changes are required.

src/main/environment/1097_ci.properties (1)

23-23: LGTM! CORS configuration property added.

The addition of cors.allowed-origins property supports the centralized CORS configuration approach, which is a good architectural improvement.

src/main/java/com/iemr/common/identity/controller/IdentityController.java (1)

85-85: LGTM! CORS annotations successfully centralized.

The systematic removal of @CrossOrigin annotations from all endpoints is consistent with the centralized CORS configuration approach, which improves maintainability and reduces code duplication.

Also applies to: 114-114, 139-139, 174-174, 205-205, 237-237, 269-269, 299-299, 324-324, 344-344, 378-378, 510-510, 617-617, 637-637, 663-663, 695-695, 794-794, 818-818, 832-832, 959-959, 974-974

src/main/java/com/iemr/common/identity/repo/iemr/EmployeeMasterRepo.java (1)

7-8: LGTM! Repository structure is well-designed.

The repository properly extends JpaRepository and is correctly annotated with @Repository. This supports the JWT authentication functionality mentioned in the AI summary.

src/main/java/com/iemr/common/identity/config/CorsConfig.java (1)

1-25: CORS configuration implementation is solid.

The implementation correctly uses allowedOriginPatterns() instead of the deprecated allowedOrigins() method, and properly configures all necessary CORS settings including credentials, exposed headers, and preflight caching.

🧰 Tools
πŸͺ› GitHub Actions: CodeQL

[warning] 23-23: ';' is preceded with whitespace.

πŸͺ› GitHub Actions: Package

[warning] 23-23: Checkstyle warning: ';' is preceded with whitespace.

pom.xml (1)

238-256: JWT dependencies look current and properly configured.

The JWT dependencies (version 0.12.6) are recent and the scope configuration is appropriate with jjwt-impl and jjwt-jackson set to runtime scope.

src/main/java/com/iemr/common/identity/domain/iemr/M_User.java (1)

10-19: Well-implemented JPA entity structure.

The JPA entity is properly configured with appropriate annotations for table mapping, ID generation, and column mappings.

src/main/java/com/iemr/common/identity/utils/CookieUtil.java (1)

13-23: Well-implemented cookie retrieval with null safety.

The cookie retrieval method properly handles null cookies and uses Optional for safe value extraction.

src/main/java/com/iemr/common/identity/utils/JwtAuthenticationUtil.java (1)

64-90: Well-implemented JWT validation with comprehensive error handling.

The method properly validates JWT tokens, extracts claims, and handles errors with appropriate exception wrapping and logging.

src/main/java/com/iemr/common/identity/utils/JwtUtil.java (1)

52-54: Note potential exception handling inconsistency.

This method delegates to extractAllClaims() which doesn't handle exceptions the same way as validateToken().

The extractAllClaims() method (lines 82-84) will throw runtime exceptions on invalid tokens, while validateToken() returns null. This creates inconsistent behavior - consider whether all token validation should follow the same error handling pattern.

# FHIR Config
fhir-url=http://localhost:8093/
fhir-url=http://localhost:8093/
cors.allowed-origins=*
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

πŸ› οΈ Refactor suggestion

Security concern: Overly permissive CORS configuration.

The wildcard * value allows any domain to make cross-origin requests, which could pose security risks including CSRF attacks and unauthorized data access. Consider restricting this to specific trusted domains in production environments.

For production use, replace the wildcard with specific domains:

-cors.allowed-origins=*
+cors.allowed-origins=https://yourtrustedomain.com,https://anothertrustedomain.com
πŸ“ Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
cors.allowed-origins=*
-cors.allowed-origins=*
+cors.allowed-origins=https://yourtrustedomain.com,https://anothertrustedomain.com
πŸ€– Prompt for AI Agents
In src/main/environment/common_example.properties at line 17, the CORS
configuration uses a wildcard '*' for allowed origins, which is insecure for
production. Replace the '*' with a comma-separated list of specific trusted
domain URLs to restrict cross-origin requests only to those domains, enhancing
security and preventing unauthorized access.


# FHIR Config
fhir-url=@FHIR_API@
logging.file.name=@env.IDENTITY_API_LOGGING_FILE_NAME@
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Remove duplicate logging configuration.

The logging.file.name property is already defined on line 9. This duplicate definition could cause confusion and unpredictable behavior.

-logging.file.name=@env.IDENTITY_API_LOGGING_FILE_NAME@
πŸ“ Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
logging.file.name=@env.IDENTITY_API_LOGGING_FILE_NAME@
πŸ€– Prompt for AI Agents
In src/main/environment/common_ci.properties at line 21, remove the duplicate
definition of the property logging.file.name since it is already defined at line
9. This will prevent confusion and ensure consistent logging configuration.

# FHIR Config
fhir-url=http://localhost:8093/
fhir-url=http://localhost:8093/
cors.allowed-origins=
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

πŸ› οΈ Refactor suggestion

Provide a meaningful default or document expected format.

An empty cors.allowed-origins property might cause runtime issues or disable CORS support entirely. Consider providing a default value or adding a comment explaining the expected format.

-cors.allowed-origins=
+# cors.allowed-origins=https://example.com,https://localhost:3000
+cors.allowed-origins=

Or provide a safe default:

-cors.allowed-origins=
+cors.allowed-origins=http://localhost:3000
πŸ€– Prompt for AI Agents
In src/main/environment/1097_example.properties at line 18, the
cors.allowed-origins property is empty, which can cause runtime issues or
disable CORS support. Fix this by either setting a meaningful default value such
as a wildcard or localhost URL, or add a comment above this line explaining the
expected format and usage of this property to guide users on how to configure it
properly.


# FHIR Config
fhir-url=@FHIR_API@
logging.file.name=@env.IDENTITY_API_1097_LOGGING_FILE_NAME@
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Remove duplicate property definition.

The logging.file.name property is already defined on line 9. Having duplicate property definitions can cause confusion and potential configuration issues.

Apply this diff to remove the duplicate:

-logging.file.name=@env.IDENTITY_API_1097_LOGGING_FILE_NAME@
πŸ“ Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
logging.file.name=@env.IDENTITY_API_1097_LOGGING_FILE_NAME@
πŸ€– Prompt for AI Agents
In src/main/environment/1097_ci.properties at line 21, remove the duplicate
definition of the property logging.file.name since it is already defined at line
9. Delete the entire line 21 to avoid confusion and potential configuration
conflicts.

Comment on lines +9 to +11
M_User findByUserID(Integer userID);

M_User getUserByUserID(Integer parseLong);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

πŸ› οΈ Refactor suggestion

Remove duplicate method and fix misleading parameter name.

The repository has two methods that appear to serve the same purpose, and the parameter name parseLong is misleading since the type is Integer.

Apply this diff to clean up the repository:

 @Repository
 public interface EmployeeMasterRepo extends JpaRepository<M_User,Integer> {
     M_User findByUserID(Integer userID);
-
-    M_User getUserByUserID(Integer parseLong);
 }

Reasons for this change:

  1. Eliminate duplication: Both methods appear to fetch user by ID
  2. Follow Spring Data conventions: findByUserID follows standard naming patterns
  3. Remove confusion: The parameter name parseLong suggests a different data type than Integer

If getUserByUserID has different behavior, please clarify its purpose and add appropriate documentation.

πŸ“ Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
M_User findByUserID(Integer userID);
M_User getUserByUserID(Integer parseLong);
@Repository
public interface EmployeeMasterRepo extends JpaRepository<M_User, Integer> {
M_User findByUserID(Integer userID);
}
πŸ€– Prompt for AI Agents
In src/main/java/com/iemr/common/identity/repo/iemr/EmployeeMasterRepo.java
around lines 9 to 11, remove the duplicate method getUserByUserID since it
duplicates findByUserID functionality. Also, rename the parameter in
findByUserID to a clear and consistent name like userID instead of parseLong to
avoid confusion about its type. Ensure only one method remains that follows
Spring Data naming conventions and clearly documents its purpose.

Comment on lines +32 to +40
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();
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

πŸ› οΈ Refactor suggestion

Add input validation and clarify userId type.

The method lacks input validation and has potential type inconsistency.

Add input validation and consider the userId type:

 public String generateToken(String username, String userId) {
+    if (username == null || username.trim().isEmpty()) {
+        throw new IllegalArgumentException("Username cannot be null or empty");
+    }
+    if (userId == null || userId.trim().isEmpty()) {
+        throw new IllegalArgumentException("UserId cannot be null or empty");
+    }
+    
     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();
 }

Consider if userId should be Integer instead of String for consistency with extractUserId() return type.

πŸ“ Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
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();
}
public String generateToken(String username, String userId) {
if (username == null || username.trim().isEmpty()) {
throw new IllegalArgumentException("Username cannot be null or empty");
}
if (userId == null || userId.trim().isEmpty()) {
throw new IllegalArgumentException("UserId cannot be null or empty");
}
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();
}
πŸ€– Prompt for AI Agents
In src/main/java/com/iemr/common/identity/utils/JwtUtil.java around lines 32 to
40, add input validation to check that username and userId are not null or empty
before proceeding. Also, change the userId parameter type from String to Integer
to match the return type of extractUserId(), and convert it to String when
adding it as a claim in the JWT. This ensures type consistency and prevents
invalid inputs.

Comment on lines +18 to +21
@Value("${jwt.secret}")
private String SECRET_KEY;

private static final long EXPIRATION_TIME = 24L * 60 * 60 * 1000; // 1 day in milliseconds
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix naming convention and enhance security validation.

The SECRET_KEY field violates Java naming conventions and lacks security validation.

Apply this diff to fix the naming convention issue flagged by the pipeline:

-    @Value("${jwt.secret}")
-    private String SECRET_KEY;
+    @Value("${jwt.secret}")
+    private String secretKey;

Additionally, consider adding validation for minimum key length to ensure security:

+    @PostConstruct
+    private void validateSecretKey() {
+        if (secretKey == null || secretKey.length() < 32) {
+            throw new IllegalStateException("JWT secret key must be at least 32 characters long");
+        }
+    }
πŸ“ Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@Value("${jwt.secret}")
private String SECRET_KEY;
private static final long EXPIRATION_TIME = 24L * 60 * 60 * 1000; // 1 day in milliseconds
@Value("${jwt.secret}")
private String secretKey;
private static final long EXPIRATION_TIME = 24L * 60 * 60 * 1000; // 1 day in milliseconds
@PostConstruct
private void validateSecretKey() {
if (secretKey == null || secretKey.length() < 32) {
throw new IllegalStateException("JWT secret key must be at least 32 characters long");
}
}
🧰 Tools
πŸͺ› GitHub Actions: Package

[warning] 19-19: Member name 'SECRET_KEY' does not match naming pattern.

πŸͺ› GitHub Actions: CodeQL

[warning] 19-19: Member name 'SECRET_KEY' does not match naming pattern.

πŸ€– Prompt for AI Agents
In src/main/java/com/iemr/common/identity/utils/JwtUtil.java around lines 18 to
21, rename the field SECRET_KEY to secretKey to follow Java naming conventions
for private fields. Additionally, add validation logic to check that the
secretKey meets a minimum length requirement to enhance security, throwing an
exception or logging an error if the key is too short.

Comment on lines +77 to +84
public <T> T extractClaim(String token, Function<Claims, T> claimsResolver) {
final Claims claims = extractAllClaims(token);
return claimsResolver.apply(claims);
}

private Claims extractAllClaims(String token) {
return Jwts.parser().setSigningKey(getSigningKey()).build().parseClaimsJws(token).getBody();
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

πŸ› οΈ Refactor suggestion

Eliminate code duplication and inconsistent exception handling.

The extractAllClaims method duplicates JWT parsing logic and has inconsistent exception handling.

Consolidate the parsing logic:

 public <T> T extractClaim(String token, Function<Claims, T> claimsResolver) {
-    final Claims claims = extractAllClaims(token);
+    final Claims claims = validateToken(token);
+    if (claims == null) {
+        throw new IllegalArgumentException("Invalid or expired JWT token");
+    }
     return claimsResolver.apply(claims);
 }

-private Claims extractAllClaims(String token) {
-    return Jwts.parser().setSigningKey(getSigningKey()).build().parseClaimsJws(token).getBody();
-}

This eliminates code duplication and makes error handling consistent across all methods.

Committable suggestion skipped: line range outside the PR's diff.

πŸ€– Prompt for AI Agents
In src/main/java/com/iemr/common/identity/utils/JwtUtil.java around lines 77 to
84, the extractAllClaims method duplicates JWT parsing logic and handles
exceptions inconsistently. Refactor by consolidating the JWT parsing logic into
a single private method that all claim extraction methods use. Ensure this
method consistently handles exceptions by catching JWT parsing errors and
rethrowing or logging them uniformly, so all methods share the same error
handling behavior and code duplication is eliminated.

Comment on lines +56 to +74
public Integer extractUserId(String jwtToken) throws IEMRException {
try {
// Validate JWT token and extract claims
Claims claims = validateToken(jwtToken);

if (claims == null) {
throw new IEMRException("Invalid JWT token.");
}

String userId = claims.get("userId", String.class);

return Integer.parseInt(userId);

} catch (Exception e) {
throw new IEMRException("Validation error: " + e.getMessage(), e);
}


}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

πŸ› οΈ Refactor suggestion

Improve efficiency and clean up formatting.

The method has redundant validation and formatting issues.

Apply this diff to improve efficiency and formatting:

-    public Integer extractUserId(String  jwtToken) throws IEMRException {
+    public Integer extractUserId(String jwtToken) throws IEMRException {
+        if (jwtToken == null || jwtToken.trim().isEmpty()) {
+            throw new IEMRException("JWT token cannot be null or empty");
+        }
+        
         try {
-            // Validate JWT token and extract claims
-            Claims claims = validateToken(jwtToken);
-
-            if (claims == null) {
-                throw new IEMRException("Invalid JWT token.");
-            }
-
-            String userId = claims.get("userId", String.class);
-
-            return  Integer.parseInt(userId);
-
+            return extractClaim(jwtToken, claims -> {
+                String userId = claims.get("userId", String.class);
+                if (userId == null) {
+                    throw new RuntimeException("UserId claim not found in token");
+                }
+                return Integer.parseInt(userId);
+            });
         } catch (Exception e) {
             throw new IEMRException("Validation error: " + e.getMessage(), e);
         }
-
-
     }

This eliminates redundant validation and uses the existing extractClaim pattern.

Committable suggestion skipped: line range outside the PR's diff.

πŸ€– Prompt for AI Agents
In src/main/java/com/iemr/common/identity/utils/JwtUtil.java between lines 56
and 74, the extractUserId method redundantly validates the token and has
formatting inconsistencies. Refactor the method to remove the redundant
validateToken call by leveraging the existing extractClaim method to retrieve
the userId claim directly. Clean up the formatting to ensure consistent spacing
and indentation, and handle exceptions appropriately by wrapping them in
IEMRException with clear messages.

Comment on lines +43 to +49
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
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

πŸ’‘ Verification agent

🧩 Analysis chain

Add input validation and consider error handling consistency.

The method lacks input validation and uses inconsistent error handling compared to other methods in the class.

Add input validation:

 public Claims validateToken(String token) {
+    if (token == null || token.trim().isEmpty()) {
+        return null;
+    }
     try {
         return Jwts.parser().setSigningKey(getSigningKey()).build().parseClaimsJws(token).getBody();
     } catch (Exception e) {
         return null; // Handle token parsing/validation errors
     }
 }

Consider whether this method should throw IEMRException like extractUserId() for consistency. The current null-return pattern is used by JwtAuthenticationUtil.validateJwtToken(), but other methods throw exceptions.


🏁 Script executed:

#!/bin/bash
# Display JwtUtil.java to inspect methods and error handling patterns
file="src/main/java/com/iemr/common/identity/utils/JwtUtil.java"
echo "=== File: $file ==="
sed -n '1,200p' "$file"
echo "..."
sed -n '200,400p' "$file"

# Search for extractUserId, extractAllClaims, and IEMRException usage
echo -e "\n=== extractUserId occurrences ==="
grep -R "extractUserId" -n "$file" || echo "Not found"
echo -e "\n=== extractAllClaims occurrences ==="
grep -R "extractAllClaims" -n "$file" || echo "Not found"
echo -e "\n=== IEMRException occurrences in JwtUtil.java ==="
grep -R "IEMRException" -n "$file" || echo "Not found"

# Search globally for IEMRException to see how it's used elsewhere
echo -e "\n=== Global IEMRException usage ==="
grep -R "class .*IEMRException" -n src
grep -R "throw new IEMRException" -n src

Length of output: 9208


🏁 Script executed:

#!/bin/bash
# Display JwtAuthenticationUtil.java around validateJwtToken
file="src/main/java/com/iemr/common/identity/utils/JwtAuthenticationUtil.java"
echo "=== File: $file ==="
sed -n '1,200p' "$file"
echo "..."
sed -n '200,400p' "$file"

Length of output: 4952


Add null/empty check in validateToken and align error handling

Please update JwtUtil.validateToken to guard against null or blank input and review your JWT‐parsing methods for consistent error handling:

β€’ File: src/main/java/com/iemr/common/identity/utils/JwtUtil.java (lines 43–49)
– Add a check at the top of validateToken to return null if token is null or empty.
– Consider whether you want to continue returning null here (as callers do in JwtAuthenticationUtil.validateJwtToken and extractUserId) or switch to throwing an IEMRException for all parse failures.

β€’ Also note: extractAllClaims (private, line 82) bypasses this null check and lets parsing exceptions bubble upβ€”if you choose to centralize behavior, have it delegate to validateToken.

Suggested diff:

 public Claims validateToken(String token) {
+    if (token == null || token.trim().isEmpty()) {
+        return null;
+    }
     try {
         return Jwts.parser()
                    .setSigningKey(getSigningKey())
                    .build()
                    .parseClaimsJws(token)
                    .getBody();
     } catch (Exception e) {
         return null; // consider throwing IEMRException for consistency
     }
 }
πŸ“ Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
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 Claims validateToken(String token) {
if (token == null || token.trim().isEmpty()) {
return null;
}
try {
return Jwts.parser()
.setSigningKey(getSigningKey())
.build()
.parseClaimsJws(token)
.getBody();
} catch (Exception e) {
return null; // consider throwing IEMRException for consistency
}
}
πŸ€– Prompt for AI Agents
In src/main/java/com/iemr/common/identity/utils/JwtUtil.java lines 43 to 49, add
a null or empty check at the start of validateToken to return null immediately
if the token is null or blank. Then, review the error handling strategy for
consistency: either keep returning null on parse failures as currently done or
throw IEMRException like extractUserId does. If you want consistent centralized
parsing, consider having extractAllClaims delegate to validateToken and unify
exception handling accordingly.

@vishwab1 vishwab1 closed this Jun 24, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants