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/mmu/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");

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 +90 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: Authentication bypass for mobile clients.

The code allows mobile clients with an Authorization header to bypass JWT validation entirely. While this matches the PR objective, it introduces a potential security risk, especially since User-Agent headers can be spoofed.

Please verify:

  1. Is the Authorization header properly validated elsewhere in the request pipeline?
  2. Is there a more robust way to identify legitimate mobile clients beyond the User-Agent?
  3. What is the security impact of this bypass?

🏁 Script executed:

#!/bin/bash
# Check if Authorization header is validated elsewhere
echo "Searching for Authorization header validation in the codebase..."
rg -A 5 "getHeader\(\"Authorization\"\)" --glob "*.java"

Length of output: 2256


Authentication bypass for mobile clients must be addressed

The filter’s if (userAgent != null && isMobileClient(userAgent) && authHeader != null) block lets any request with a spoofable User-Agent and a non-empty Authorization header skip JWT validation entirely. We did not find any other point in the pipeline that verifies the header’s token.

• File to fix:

  • src/main/java/com/iemr/mmu/utils/JwtUserIdValidationFilter.java (around lines 90–93)

• Recommendations:

  1. Remove or tighten this bypass. Instead of simply checking authHeader != null, parse and validate the JWT via jwtAuthenticationUtil.validateUserIdAndJwtToken(...).
  2. If you must exempt certain mobile clients, identify them with a stronger mechanism—e.g., API-key or client certificate, device fingerprinting, or a dedicated mobile OAuth flow (PKCE)—not by User-Agent.
  3. Assess the impact: as written, any attacker can spoof the User-Agent header and supply a dummy Authorization value to gain unauthorized access.
🤖 Prompt for AI Agents
In src/main/java/com/iemr/mmu/utils/JwtUserIdValidationFilter.java around lines
90 to 93, the current code bypasses JWT validation for mobile clients based
solely on the User-Agent and presence of an Authorization header, which is
insecure due to header spoofing. To fix this, remove this bypass or replace the
condition to parse and validate the JWT token using
jwtAuthenticationUtil.validateUserIdAndJwtToken(...) before allowing the request
to proceed. If any exemption for mobile clients is necessary, implement a
stronger client verification method such as API keys, client certificates, or a
dedicated OAuth flow instead of relying on User-Agent. This ensures proper
authentication and prevents unauthorized access.


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: " + e.getMessage());
}
}

private boolean isMobileClient(String userAgent) {
if (userAgent == null)
return false;
userAgent = userAgent.toLowerCase();
return userAgent.contains("okhttp"); // iOS (custom clients)
}
private String getJwtTokenFromCookies(HttpServletRequest request) {
Cookie[] cookies = request.getCookies();
if (cookies != null) {
Expand Down
Loading