Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 31 additions & 16 deletions src/main/java/com/iemr/admin/utils/JwtUserIdValidationFilter.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,32 +65,47 @@ public void doFilter(ServletRequest servletRequest, ServletResponse servletRespo
}

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;
String jwtFromCookie = getJwtTokenFromCookies(request);
String jwtFromHeader = request.getHeader("JwtToken");
String authHeader = request.getHeader("Authorization");

Comment on lines +68 to +71
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Inconsistent JWT token header naming.

There's an inconsistency between the JWT token header name used in initial logging (line 52: "Jwttoken") and the one used for actual validation (line 69: "JwtToken"). This case difference could cause the header check to fail if clients are using the case shown in the logging statement.

- String jwtFromHeader = request.getHeader("JwtToken");
+ String jwtFromHeader = request.getHeader("Jwttoken");

Also, consider using constants for header names to maintain consistency throughout the code.

πŸ“ 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
String jwtFromCookie = getJwtTokenFromCookies(request);
String jwtFromHeader = request.getHeader("JwtToken");
String authHeader = request.getHeader("Authorization");
String jwtFromCookie = getJwtTokenFromCookies(request);
- String jwtFromHeader = request.getHeader("JwtToken");
+ String jwtFromHeader = request.getHeader("Jwttoken");
String authHeader = request.getHeader("Authorization");
πŸ€– Prompt for AI Agents
In src/main/java/com/iemr/admin/utils/JwtUserIdValidationFilter.java around
lines 52 and 69, the JWT token header name is inconsistently cased ("Jwttoken"
vs "JwtToken"), which can cause header retrieval failures. Standardize the
header name casing across all usages to be identical. Additionally, define a
constant for the JWT token header name and replace all hardcoded instances with
this constant to ensure consistency and easier maintenance.

if (jwtFromCookie != null) {
logger.info("Validating JWT token from cookie");
if (jwtAuthenticationUtil.validateUserIdAndJwtToken(jwtFromCookie)) {
filterChain.doFilter(servletRequest, servletResponse);
return;
}
}

// Validate JWT token and userId
boolean isValid = jwtAuthenticationUtil.validateUserIdAndJwtToken(jwtToken);
if (jwtFromHeader != null) {
logger.info("Validating JWT token from header");
if (jwtAuthenticationUtil.validateUserIdAndJwtToken(jwtFromHeader)) {
filterChain.doFilter(servletRequest, servletResponse);
return;
}
}
String userAgent = request.getHeader("User-Agent");
logger.info("User-Agent: " + userAgent);

if (isValid) {
// If token is valid, allow the request to proceed
if (userAgent != null && isMobileClient(userAgent) && authHeader != null) {
filterChain.doFilter(servletRequest, servletResponse);
} else {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Invalid JWT token");
return;
}
Comment on lines +87 to 93
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

Security concern with mobile client bypass.

Allowing mobile clients to bypass JWT validation based solely on User-Agent and presence of an Authorization header creates a security vulnerability. The User-Agent can be easily spoofed.

Consider implementing a more robust authentication mechanism for mobile clients. At minimum, verify that the Authorization header contains a valid token:


🏁 Script executed:

#!/bin/bash
# Check if there's any validation for the Authorization header elsewhere in the codebase
rg -A 3 "Authorization.*header" --type java

Length of output: 45


🏁 Script executed:

#!/bin/bash
# Locate where the Authorization header is retrieved
rg -n 'getHeader.*"Authorization"' -A 3 --type java

# Show all occurrences of the local variable authHeader for context
rg -n 'authHeader' -A 5 --type java

Length of output: 4717


Ensure JWT validation for mobile clients, not just header presence

The current logic in JwtUserIdValidationFilter.java (around lines 87–93) skips any real token check for mobile UAs:

String userAgent = request.getHeader("User-Agent");
if (userAgent != null && isMobileClient(userAgent) && authHeader != null) {
    filterChain.doFilter(servletRequest, servletResponse);
    return;
}

User-Agent values are trivial to spoofβ€”allowing any non-null Authorization header effectively opens a backdoor. You should validate the token in the header just as you do for the cookie:

β€’ File: src/main/java/com/iemr/admin/utils/JwtUserIdValidationFilter.java
β€’ Lines: ~87–93

Suggested change:

- if (userAgent != null && isMobileClient(userAgent) && authHeader != null) {
-     filterChain.doFilter(servletRequest, servletResponse);
-     return;
- }
+ if (userAgent != null && isMobileClient(userAgent) && authHeader != null) {
+     logger.info("Validating JWT token from Authorization header for mobile client");
+     if (jwtAuthenticationUtil.validateUserIdAndJwtToken(authHeader)) {
+         filterChain.doFilter(servletRequest, servletResponse);
+         return;
+     }
+     logger.warn("Invalid JWT token in Authorization header for mobile client");
+ }

This ensures mobile clients can’t bypass authentication by spoofing User-Agent.

πŸ€– Prompt for AI Agents
In src/main/java/com/iemr/admin/utils/JwtUserIdValidationFilter.java around
lines 87 to 93, the code currently bypasses JWT validation for mobile clients if
the User-Agent header indicates a mobile client and the Authorization header is
present, which is insecure due to easy User-Agent spoofing. To fix this, remove
the bypass condition and instead validate the JWT token in the Authorization
header for mobile clients just as you do for other clients, ensuring the token
is properly parsed and verified before allowing the request to proceed.


logger.warn("No valid authentication token found");
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized: Invalid or missing token");

} catch (Exception e) {
logger.error("Authorization error: ", e);
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Authorization error: ");
}
}

private boolean isMobileClient(String userAgent) {
if (userAgent == null)
return false;
userAgent = userAgent.toLowerCase();
return userAgent.contains("okhttp");
}
Comment on lines +103 to +108
Copy link

Choose a reason for hiding this comment

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

πŸ› οΈ Refactor suggestion

Mobile client detection is too simplistic.

The mobile client detection relies solely on checking for "okhttp" in the User-Agent string. This is fragile and can be easily circumvented.

Consider:

  1. Using a more comprehensive list of mobile client identifiers
  2. Implementing additional verification methods beyond User-Agent
  3. Creating a configurable list of trusted mobile clients
private boolean isMobileClient(String userAgent) {
    if (userAgent == null)
        return false;
    userAgent = userAgent.toLowerCase();
-   return userAgent.contains("okhttp");
+   // Check for common mobile client indicators
+   return userAgent.contains("okhttp") || 
+          userAgent.contains("android") || 
+          userAgent.contains("iphone") || 
+          userAgent.contains("mobile");
}
πŸ“ 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
private boolean isMobileClient(String userAgent) {
if (userAgent == null)
return false;
userAgent = userAgent.toLowerCase();
return userAgent.contains("okhttp");
}
private boolean isMobileClient(String userAgent) {
if (userAgent == null)
return false;
userAgent = userAgent.toLowerCase();
// Check for common mobile client indicators
return userAgent.contains("okhttp") ||
userAgent.contains("android") ||
userAgent.contains("iphone") ||
userAgent.contains("mobile");
}
πŸ€– Prompt for AI Agents
In src/main/java/com/iemr/admin/utils/JwtUserIdValidationFilter.java around
lines 103 to 108, the current mobile client detection only checks if the
User-Agent contains "okhttp", which is too simplistic and unreliable. To fix
this, replace the hardcoded check with a configurable list of trusted mobile
client identifiers and update the method to check if the User-Agent matches any
entry in this list. Additionally, consider implementing extra verification
methods beyond User-Agent to improve detection accuracy.

private String getJwtTokenFromCookies(HttpServletRequest request) {
Cookie[] cookies = request.getCookies();
if (cookies != null) {
Expand Down
Loading