Skip to content

Conversation

ravishanigarapu
Copy link
Member

@ravishanigarapu ravishanigarapu commented Sep 25, 2025

πŸ“‹ Description

JIRA ID: AMM-1845

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
    • Token refresh is now available for users with status β€œNew,” not just β€œActive,” improving the experience for newly onboarded users.
    • The refresh token endpoint can be accessed without prior authentication, allowing smoother session recovery when access tokens expire.
    • Existing token flows continue to work as before; users whose status is neither Active nor New will remain unauthorized for refresh.

Copy link
Contributor

coderabbitai bot commented Sep 25, 2025

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

The refreshToken endpoint now allows users with status Active or New to refresh tokens. The authentication filter was updated to skip authentication for /user/refreshToken, similar to /user/logOutUserFromConcurrentSession. No public API signatures changed.

Changes

Cohort / File(s) Summary
Auth Controller: refreshToken status check
src/main/java/com/iemr/common/controller/users/IEMRAdminController.java
Broadened user status validation in refreshToken to accept both Active and New; unauthorized only when status is neither.
Auth Filter: skip rule for refreshToken
src/main/java/com/iemr/common/utils/JwtUserIdValidationFilter.java
Added /user/refreshToken to shouldSkipAuthentication conditions; no other logic changes.

Sequence Diagram(s)

sequenceDiagram
  participant C as Client
  participant F as JwtUserIdValidationFilter
  participant A as IEMRAdminController
  participant U as UserService
  participant T as TokenService

  rect rgba(200,220,255,0.25)
  note over F: Updated skip condition
  C->>F: HTTP POST /user/refreshToken
  alt Path is /user/refreshToken
    F-->>C: Skip auth (proceed)
  else Other paths
    F->>F: Validate JWT
  end
  end

  C->>A: refreshToken request
  A->>U: Load user by token/userId
  U-->>A: User(status)
  alt status in {Active, New}
    A->>T: Generate new token
    T-->>A: Token
    A-->>C: 200 OK (token)
  else
    A-->>C: 401 Unauthorized
  end
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

Suggested reviewers

  • drtechie
  • helenKaryamsetty

Poem

A hop and a skip past the auth gate’s dome,
Refresh tokens bloom for New and Active home.
Filters step asideβ€”β€œProceed!” they cheer,
Keys get renewed, the path now clear.
Thump-thump joy in the server’s den,
Another tokenβ€”hip hop again! πŸ‡πŸ”‘

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
βœ… Passed checks (2 passed)
Check name Status Explanation
Description Check βœ… Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check βœ… Passed The title directly references the refresh token authorization issue that this PR resolves by expanding valid statuses and skipping authentication on the refresh endpoint, so it is aligned with the main change.

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

Comment @coderabbitai help to get the list of available commands and usage tips.

@ravishanigarapu
Copy link
Member Author

@coderabbitai review

Copy link
Contributor

coderabbitai bot commented Sep 25, 2025

βœ… Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Contributor

@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: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/main/java/com/iemr/common/controller/users/IEMRAdminController.java (1)

270-276: Refresh token rotation is incomplete: the used refresh token (old JTI) is not revoked.

Without deleting the used JTI, a stolen refresh token can be reused until expiry. Revoke it upon successful rotation.

Apply this diff:

             String jti = claims.getId();
             if (!redisTemplate.hasKey("refresh:" + jti)) {
                 logger.warn("Token validation failed: refresh token is revoked or not found in store.");
                 return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Unauthorized.");
             }
+            // Rotate: revoke the used refresh token (one-time use)
+            redisTemplate.delete("refresh:" + jti);
@@
             String newRefreshToken = jwtUtil.generateRefreshToken(user.getUserName(), userId);
             String newJti = jwtUtil.getJtiFromToken(newRefreshToken);
             redisTemplate.opsForValue().set(
                 "refresh:" + newJti,
                 userId,
                 jwtUtil.getRefreshTokenExpiration(),
                 TimeUnit.MILLISECONDS
             );

Optional hardening (future): store a short-lived β€œused:” marker to detect/token-ban refresh token reuse.

Also applies to: 299-307

🧹 Nitpick comments (2)
src/main/java/com/iemr/common/utils/JwtUserIdValidationFilter.java (2)

172-172: Remove duplicate skip condition for logOutUserFromConcurrentSession.

This endpoint is already covered earlier with equalsIgnoreCase. The duplicate startsWith adds noise without benefit.

Apply this diff:

-                || path.startsWith(contextPath + "/user/logOutUserFromConcurrentSession")

173-174: Avoid redundant skip for refreshToken (equals + startsWith).

Keep one form (prefer equals for exact match) to reduce confusion.

If you want to retain only the exact match (already present above), remove these lines:

-                || path.startsWith(contextPath + "/user/refreshToken");
+                ;

Alternatively, if you want startsWith behavior, drop the earlier equals(...) check instead.

πŸ“œ Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between c181b2a and 7b9cd2a.

πŸ“’ Files selected for processing (2)
  • src/main/java/com/iemr/common/controller/users/IEMRAdminController.java (1 hunks)
  • src/main/java/com/iemr/common/utils/JwtUserIdValidationFilter.java (1 hunks)
πŸ”‡ Additional comments (1)
src/main/java/com/iemr/common/controller/users/IEMRAdminController.java (1)

288-289: Allowing 'New' status for refresh looks correct.

Matches the PR objective to unblock refresh for Active or New users.

if (user.getM_status() == null || !"Active".equalsIgnoreCase(user.getM_status().getStatus())) {
if (user.getM_status() == null || !("Active".equalsIgnoreCase(user.getM_status().getStatus())
|| "New".equalsIgnoreCase(user.getM_status().getStatus()))) {
logger.warn("Token validation failed: user account is inactive or not in 'Active' status.");
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟑 Minor

Fix log message to reflect the broadened rule.

It still mentions only 'Active'.

Apply this diff:

-                logger.warn("Token validation failed: user account is inactive or not in 'Active' status.");
+                logger.warn("Token validation failed: user account is neither 'Active' nor 'New'.");
πŸ“ 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
logger.warn("Token validation failed: user account is inactive or not in 'Active' status.");
logger.warn("Token validation failed: user account is neither 'Active' nor 'New'.");
πŸ€– Prompt for AI Agents
In src/main/java/com/iemr/common/controller/users/IEMRAdminController.java
around line 290, the logger.warn message still references only 'Active' even
though the rule was broadened; update the warning text to reflect the broader
rule (e.g., state that token validation failed because the user account is
inactive or not in an allowed/valid status) so the log accurately describes the
condition.

Copy link

@ravishanigarapu ravishanigarapu merged commit f93e2f4 into release-3.6.0 Sep 25, 2025
2 checks passed
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.

2 participants