Skip to content

[ES-2950][ES-2953] fixed htu and iat claim validation in dpop jwt#1669

Open
sacrana0 wants to merge 2 commits intomosip:developfrom
Infosys:sachin-dev
Open

[ES-2950][ES-2953] fixed htu and iat claim validation in dpop jwt#1669
sacrana0 wants to merge 2 commits intomosip:developfrom
Infosys:sachin-dev

Conversation

@sacrana0
Copy link
Contributor

@sacrana0 sacrana0 commented Mar 16, 2026

Summary by CodeRabbit

  • New Features

    • Strengthened DPoP validation: normalizes request URI (ignoring query/fragment), enforces HTU/HTM claims, and validates iat freshness with clock-skew tolerance.
  • Behavior Changes

    • Invalid DPoP proofs now yield consistent error responses and block request processing on failure.
  • Tests

    • Added tests for HTU with query/fragment and iat outside allowed time window.
  • Configuration

    • Added configurable DPoP iat max-age property.

@coderabbitai
Copy link

coderabbitai bot commented Mar 16, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: eabcbd04-4434-4c8e-8086-37dd9c3633e3

📥 Commits

Reviewing files that changed from the base of the PR and between ef3640c and 9f4472f.

📒 Files selected for processing (1)
  • esignet-service/src/test/resources/application-test.properties
✅ Files skipped from review due to trivial changes (1)
  • esignet-service/src/test/resources/application-test.properties

Walkthrough

Adds HTU normalization/validation (strips query/fragment) and IAT validation with clock‑skew tolerance and configurable max age to DPoP verification; switches claim verifier to a parameterized DefaultJWTClaimsVerifier, centralizes InvalidDpopHeaderException handling, and adds unit tests and config property.

Changes

Cohort / File(s) Summary
DPoP Claim Validation
esignet-service/src/main/java/io/mosip/esignet/advice/DpopValidationFilter.java
Adds HTU normalization (strip query and fragment) and comparison, adds IAT validation with clock‑skew and configurable max age, replaces claim verification with DefaultJWTClaimsVerifier<SecurityContext>, introduces HTU/HTM constants, centralizes error handling to throw InvalidDpopHeaderException, and updates imports.
DPoP Validation Tests
esignet-service/src/test/java/io/mosip/esignet/advice/DpopValidationFilterTest.java
Initializes maxClockSkewSeconds and maxDPOPIatAgeSeconds in setup; adds testHtuClaimWithQueryParamsAndFragment_thenPass() and testDpopHeader_withIatOutsideTimeLimit_thenFail() covering HTU normalization and IAT age validation/failure behavior.
Configuration
esignet-service/src/main/resources/application-default.properties, esignet-service/src/test/resources/application-test.properties
Adds mosip.esignet.dpop.iat.max-age-seconds=60 to default and test properties and updates related clock‑skew/iat/exp comment in defaults.

Sequence Diagram(s)

sequenceDiagram
    participant Client as Client
    participant Filter as DpopValidationFilter
    participant Verifier as DefaultJWTClaimsVerifier<SecurityContext>
    participant TimeCheck as IAT/ClockSkewChecker
    participant Chain as FilterChain/Controller
    participant Error as InvalidDpopHandler

    Client->>Filter: HTTP request with DPoP proof
    Filter->>Verifier: Verify JWT claims (alg, typ, nonce, HTM/HTU presence)
    Verifier-->>Filter: Claims map or throws
    Filter->>Filter: Normalize request URI (strip query/fragment)
    Filter->>Verifier: Compare HTU claim to normalized URI
    Filter->>TimeCheck: Validate iat within clock‑skew and max‑age
    alt all checks pass
        Filter->>Chain: forward request
        Chain-->>Client: 200 / next handler response
    else any check fails
        Filter->>Error: Log & throw InvalidDpopHeaderException
        Error-->>Client: 400 with WWW-Authenticate: INVALID_DPOP_PROOF
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐇
I nibbled query tails and trimmed the hash,
Counted ticks with care, never rash,
I matched each HTU, timed every iat,
Threw out the stale, kept what’s exact,
Now proofs hop safe across the path.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ 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%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ 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 accurately describes the main changes: it references the fixed DPoP JWT validation for htu and iat claims, directly matching the core modifications across all files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
📝 Coding Plan
  • Generate coding plan for human review comments

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.

Copy link
Contributor

@Md-Humair-KK Md-Humair-KK left a comment

Choose a reason for hiding this comment

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

Looks fine

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: 2

🧹 Nitpick comments (3)
esignet-service/src/main/java/io/mosip/esignet/advice/DpopValidationFilter.java (2)

275-288: HTU validation logic looks correct.

The stripping of query parameters and fragments before comparison is correct per RFC 9449. The null check at line 277 is defensive since DefaultJWTClaimsVerifier already validates required claims, but it provides clearer error logging.

One note: If htuClaim contains an invalid URI, the URISyntaxException will be caught by the generic Exception handler below, which logs "Invalid request URI" — that's reasonable but consider catching URISyntaxException separately for a more specific error message.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@esignet-service/src/main/java/io/mosip/esignet/advice/DpopValidationFilter.java`
around lines 275 - 288, In DpopValidationFilter, when parsing htuClaim into a
URI (the UriComponentsBuilder.fromUri(new URI(htuClaim)) call and subsequent
builder.replaceQuery/fragment), add a dedicated catch for URISyntaxException so
invalid htu URIs are logged with a clear, specific message (e.g., "Invalid htu
claim URI") and then throw InvalidDpopHeaderException; keep the existing generic
Exception handler for other cases, but ensure the URISyntaxException branch
references htuClaim and the DpopValidationFilter/htuClaim parsing logic so the
error is easy to trace.

290-299: Consider removing redundant IAT validation.

DefaultJWTClaimsVerifier.verify() (line 273) already validates that iat is present (it's in REQUIRED_CLAIMS) and not in the future beyond maxClockSkew. This manual check duplicates that logic.

If the intent is to provide more specific error logging, the current approach is acceptable. Otherwise, this block could be removed to reduce redundancy.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@esignet-service/src/main/java/io/mosip/esignet/advice/DpopValidationFilter.java`
around lines 290 - 299, The iat validation block duplicates
DefaultJWTClaimsVerifier.verify() behavior; remove the manual checks that call
claims.getIssueTime(), the null check/log ("Missing iat claim"), and the future
check against Instant.now().plusSeconds(maxClockSkewSeconds) along with the
associated throws of InvalidDpopHeaderException so the code relies on
DefaultJWTClaimsVerifier.verify() (invoked earlier) for presence and clock-skew
validation; if you want to keep a log-only record instead, replace the throw
statements with only log.debug/info calls mentioning iat and maxClockSkewSeconds
so no duplicate validation occurs.
esignet-service/src/test/java/io/mosip/esignet/advice/DpopValidationFilterTest.java (1)

339-371: Consider adding a boundary test case.

The test validates that iat 20 seconds in the future fails with 10 seconds clock skew. Consider adding a test where iat is exactly at the boundary (e.g., iat = now + 10s with maxClockSkew = 10) to verify the boundary condition behavior.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@esignet-service/src/test/java/io/mosip/esignet/advice/DpopValidationFilterTest.java`
around lines 339 - 371, Add a new test method in DpopValidationFilterTest that
creates a DPoP JWT with iat exactly set to now plus the maxClockSkewSeconds
(e.g., iat = now + 10s if maxClockSkewSeconds is 10). This will test the
boundary condition to ensure the filter either accepts or rejects the token
correctly at the clock skew limit, complementing the existing
testDpopHeader_withIatInFuture_thenFail method.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@esignet-service/src/main/java/io/mosip/esignet/advice/DpopValidationFilter.java`:
- Around line 301-304: The catch-all in DpopValidationFilter currently logs
every error as "Invalid request URI" and throws InvalidDpopHeaderException;
modify the exception handling in the block around
DefaultJWTClaimsVerifier.verify() and the URI parsing so you catch and handle
specific exceptions (e.g., BadJWTException from
DefaultJWTClaimsVerifier.verify(), JOSEException,
ParseException/URISyntaxException from URI parsing, and any other known types)
rather than Exception; for each specific catch, log a clear, distinct message
including e.getMessage() and context (e.g., "DPoP claim verification failed" for
BadJWTException, "Invalid request URI" for URI parsing), and then throw
InvalidDpopHeaderException (or wrap the original where appropriate) so callers
get correct diagnostics while preserving existing error semantics in
DpopValidationFilter.

In
`@esignet-service/src/test/java/io/mosip/esignet/advice/DpopValidationFilterTest.java`:
- Around line 358-359: Update the misleading test comment: change the line
commenting "Set clock skew to 0 so the future iat is rejected" to accurately
reflect that maxClockSkewSeconds is being set to 10 (so an iat 20s in the future
exceeds the 10s tolerance). Locate the ReflectionTestUtils.setField call that
sets "maxClockSkewSeconds" on the filter instance and adjust the comment to
mention 10 seconds tolerance (or remove the incorrect part) so it matches the
test logic.

---

Nitpick comments:
In
`@esignet-service/src/main/java/io/mosip/esignet/advice/DpopValidationFilter.java`:
- Around line 275-288: In DpopValidationFilter, when parsing htuClaim into a URI
(the UriComponentsBuilder.fromUri(new URI(htuClaim)) call and subsequent
builder.replaceQuery/fragment), add a dedicated catch for URISyntaxException so
invalid htu URIs are logged with a clear, specific message (e.g., "Invalid htu
claim URI") and then throw InvalidDpopHeaderException; keep the existing generic
Exception handler for other cases, but ensure the URISyntaxException branch
references htuClaim and the DpopValidationFilter/htuClaim parsing logic so the
error is easy to trace.
- Around line 290-299: The iat validation block duplicates
DefaultJWTClaimsVerifier.verify() behavior; remove the manual checks that call
claims.getIssueTime(), the null check/log ("Missing iat claim"), and the future
check against Instant.now().plusSeconds(maxClockSkewSeconds) along with the
associated throws of InvalidDpopHeaderException so the code relies on
DefaultJWTClaimsVerifier.verify() (invoked earlier) for presence and clock-skew
validation; if you want to keep a log-only record instead, replace the throw
statements with only log.debug/info calls mentioning iat and maxClockSkewSeconds
so no duplicate validation occurs.

In
`@esignet-service/src/test/java/io/mosip/esignet/advice/DpopValidationFilterTest.java`:
- Around line 339-371: Add a new test method in DpopValidationFilterTest that
creates a DPoP JWT with iat exactly set to now plus the maxClockSkewSeconds
(e.g., iat = now + 10s if maxClockSkewSeconds is 10). This will test the
boundary condition to ensure the filter either accepts or rejects the token
correctly at the clock skew limit, complementing the existing
testDpopHeader_withIatInFuture_thenFail method.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: b69942c2-12fe-4015-a0b9-7654fec17821

📥 Commits

Reviewing files that changed from the base of the PR and between 2fa9c2c and 3954ec6.

📒 Files selected for processing (2)
  • esignet-service/src/main/java/io/mosip/esignet/advice/DpopValidationFilter.java
  • esignet-service/src/test/java/io/mosip/esignet/advice/DpopValidationFilterTest.java

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.

🧹 Nitpick comments (1)
esignet-service/src/main/java/io/mosip/esignet/advice/DpopValidationFilter.java (1)

290-299: Consider adding a past-bound check for the iat claim.

The current validation rejects tokens issued in the future (with clock skew tolerance), but accepts tokens with arbitrarily old iat values. DPoP proofs are intended to be freshly generated per request. Without a past-bound check, a captured DPoP JWT could remain valid indefinitely (limited only by the jti replay check cache TTL).

Consider adding a maximum age constraint:

🛡️ Optional enhancement for freshness validation
             if (iat.toInstant().isAfter(Instant.now().plusSeconds(maxClockSkewSeconds))) {
                 log.error("iat claim is in the future");
                 throw new InvalidDpopHeaderException();
             }
+            // Optional: reject tokens older than a reasonable threshold (e.g., 5 minutes)
+            int maxAgeSeconds = 300; // could be configurable
+            if (iat.toInstant().isBefore(Instant.now().minusSeconds(maxAgeSeconds + maxClockSkewSeconds))) {
+                log.error("iat claim is too old");
+                throw new InvalidDpopHeaderException();
+            }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@esignet-service/src/main/java/io/mosip/esignet/advice/DpopValidationFilter.java`
around lines 290 - 299, Add a past-bound validation for the DPoP `iat` claim in
DpopValidationFilter: after obtaining claims.getIssueTime() and the existing
future check that uses maxClockSkewSeconds, also enforce a maximum age (e.g.,
maxIatAgeSeconds from config) by verifying
iat.toInstant().isBefore(Instant.now().minusSeconds(maxIatAgeSeconds)); if so,
log an error (e.g., "iat claim is too old") and throw
InvalidDpopHeaderException. Ensure you introduce/read a configurable
maxIatAgeSeconds value and use the same InvalidDpopHeaderException path as the
other iat checks.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@esignet-service/src/main/java/io/mosip/esignet/advice/DpopValidationFilter.java`:
- Around line 290-299: Add a past-bound validation for the DPoP `iat` claim in
DpopValidationFilter: after obtaining claims.getIssueTime() and the existing
future check that uses maxClockSkewSeconds, also enforce a maximum age (e.g.,
maxIatAgeSeconds from config) by verifying
iat.toInstant().isBefore(Instant.now().minusSeconds(maxIatAgeSeconds)); if so,
log an error (e.g., "iat claim is too old") and throw
InvalidDpopHeaderException. Ensure you introduce/read a configurable
maxIatAgeSeconds value and use the same InvalidDpopHeaderException path as the
other iat checks.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: d1e53530-7224-47d4-9952-acfe80ddbba5

📥 Commits

Reviewing files that changed from the base of the PR and between 3954ec6 and b17c19d.

📒 Files selected for processing (2)
  • esignet-service/src/main/java/io/mosip/esignet/advice/DpopValidationFilter.java
  • esignet-service/src/test/java/io/mosip/esignet/advice/DpopValidationFilterTest.java
🚧 Files skipped from review as they are similar to previous changes (1)
  • esignet-service/src/test/java/io/mosip/esignet/advice/DpopValidationFilterTest.java

@sacrana0
Copy link
Contributor Author

sacrana0 commented Mar 16, 2026

🧹 Nitpick comments (1)

esignet-service/src/main/java/io/mosip/esignet/advice/DpopValidationFilter.java (1)> 290-299: Consider adding a past-bound check for the iat claim.

The current validation rejects tokens issued in the future (with clock skew tolerance), but accepts tokens with arbitrarily old iat values. DPoP proofs are intended to be freshly generated per request. Without a past-bound check, a captured DPoP JWT could remain valid indefinitely (limited only by the jti replay check cache TTL).
Consider adding a maximum age constraint:

🛡️ Optional enhancement for freshness validation

             if (iat.toInstant().isAfter(Instant.now().plusSeconds(maxClockSkewSeconds))) {
                 log.error("iat claim is in the future");
                 throw new InvalidDpopHeaderException();
             }
+            // Optional: reject tokens older than a reasonable threshold (e.g., 5 minutes)
+            int maxAgeSeconds = 300; // could be configurable
+            if (iat.toInstant().isBefore(Instant.now().minusSeconds(maxAgeSeconds + maxClockSkewSeconds))) {
+                log.error("iat claim is too old");
+                throw new InvalidDpopHeaderException();
+            }

🤖 Prompt for AI Agents

Verify each finding against the current code and only fix it if needed.

In
`@esignet-service/src/main/java/io/mosip/esignet/advice/DpopValidationFilter.java`
around lines 290 - 299, Add a past-bound validation for the DPoP `iat` claim in
DpopValidationFilter: after obtaining claims.getIssueTime() and the existing
future check that uses maxClockSkewSeconds, also enforce a maximum age (e.g.,
maxIatAgeSeconds from config) by verifying
iat.toInstant().isBefore(Instant.now().minusSeconds(maxIatAgeSeconds)); if so,
log an error (e.g., "iat claim is too old") and throw
InvalidDpopHeaderException. Ensure you introduce/read a configurable
maxIatAgeSeconds value and use the same InvalidDpopHeaderException path as the
other iat checks.

🤖 Prompt for all review comments with AI agents

Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@esignet-service/src/main/java/io/mosip/esignet/advice/DpopValidationFilter.java`:
- Around line 290-299: Add a past-bound validation for the DPoP `iat` claim in
DpopValidationFilter: after obtaining claims.getIssueTime() and the existing
future check that uses maxClockSkewSeconds, also enforce a maximum age (e.g.,
maxIatAgeSeconds from config) by verifying
iat.toInstant().isBefore(Instant.now().minusSeconds(maxIatAgeSeconds)); if so,
log an error (e.g., "iat claim is too old") and throw
InvalidDpopHeaderException. Ensure you introduce/read a configurable
maxIatAgeSeconds value and use the same InvalidDpopHeaderException path as the
other iat checks.

ℹ️ Review info

@coderabbitai Can you point me to some documentation or rfc as I didn't see anything about iat validation being too old?

@sacrana0 sacrana0 closed this Mar 16, 2026
@sacrana0 sacrana0 reopened this Mar 16, 2026
@coderabbitai
Copy link

coderabbitai bot commented Mar 16, 2026

Tip

For best results, initiate chat on the files or code changes.

@sacrana0 Great question! Here's the relevant context from RFC 9449:

What RFC 9449 says about iat freshness:

Section 4.3 of RFC 9449 requires that "the creation time of the JWT, as determined by either the iat claim or a server managed timestamp via the nonce claim, is within an acceptable window." However, the RFC intentionally leaves "acceptable window" undefined for past-bound checks.

The RFC's preferred mechanism for proof lifetime:

RFC 9449 notes that "servers MAY limit DPoP proof lifetimes by using server-provided nonce values containing the time at the server rather than comparing the client-supplied iat time" and that nonces yield the same result "even in the face of arbitrarily large clock skews."

Why a past-bound iat check is still a reasonable defense-in-depth measure:

RFC 9449 Section 11.1 explicitly calls out that "an attacker in control of the client can pre-generate DPoP proofs for specific endpoints arbitrarily far into the future." It notes a legitimate user may pre-generate DPoP proofs and copy them to another machine, and "when DPoP proofs can be pre-generated and exfiltrated, all that is actually being proved in DPoP protocol interactions is possession of a DPoP proof — not of the proof-of-possession key."

Practitioner guides also echo this: the iat claim is included because "authorization servers should only accept fairly fresh DPoP tokens."


Summary: The RFC does not explicitly mandate a maximum past age for iat — you're correct that there's no hard rule. My suggestion was a defense-in-depth / security hardening recommendation, particularly useful if you are not implementing server-provided nonces. If your implementation relies on jti replay-tracking (with a bounded cache TTL) as the primary freshness mechanism, the past-bound iat check is indeed optional. I've marked my original comment as a nitpick for this reason.

You're free to skip it if your jti cache provides sufficient replay protection for your threat model. If you'd like, I can resolve that comment.

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: 2

🧹 Nitpick comments (2)
esignet-service/src/main/resources/application-default.properties (1)

25-28: Comment inaccuracy: clock-skew applies to multiple claims.

The comment at line 25 states the clock-skew validates 'nbf' and 'exp' claims, but DefaultJWTClaimsVerifier.setMaxClockSkew() applies tolerance to iat, nbf, and exp claims. Additionally, the filter now uses maxClockSkewSeconds for the custom future-iat check. Consider updating the comment to reflect all affected claims.

Also, consider documenting the relationship between clock-skew (future tolerance) and iat.max-age-seconds (past tolerance) for clarity.

📝 Suggested comment update
-# DPoP jwt clock skew in seconds to validate 'nbf' and 'exp' claim
+# DPoP jwt clock skew in seconds for iat/nbf/exp claim tolerance (future allowance)
 mosip.esignet.dpop.clock-skew=10
 mosip.esignet.dpop.nonce.expire.seconds=15
+# Maximum age in seconds for DPoP iat claim (past allowance)
 mosip.esignet.dpop.iat.max-age-seconds=60
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@esignet-service/src/main/resources/application-default.properties` around
lines 25 - 28, Update the properties comment to correctly state that
mosip.esignet.dpop.clock-skew applies to the iat, nbf and exp claims (as
enforced by DefaultJWTClaimsVerifier.setMaxClockSkew()) and note that this is
used as the future-iat tolerance (maxClockSkewSeconds) in the custom filter,
while mosip.esignet.dpop.iat.max-age-seconds controls past-age tolerance for
iat; change the single-line comment above the properties to reflect these three
affected claims and the relationship between clock-skew (future tolerance) and
iat.max-age-seconds (past tolerance).
esignet-service/src/test/java/io/mosip/esignet/advice/DpopValidationFilterTest.java (1)

340-358: Minor: Comment inaccuracy on iat offset.

The comment at line 342 states "iat set 10 seconds in the future" but line 353 actually sets Instant.now().plusSeconds(20). Consider updating the comment to reflect the actual 20-second offset.

📝 Proposed fix
-        // Build a DPoP JWT with iat set 10 seconds in the future
+        // Build a DPoP JWT with iat set 20 seconds in the future (beyond 10s clock skew tolerance)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@esignet-service/src/test/java/io/mosip/esignet/advice/DpopValidationFilterTest.java`
around lines 340 - 358, Update the inaccurate inline comment in the test method
testDpopHeader_withIatOutsideTimeLimit_thenFail: the comment currently says "iat
set 10 seconds in the future" but the code sets issueTime to
Instant.now().plusSeconds(20); change the comment to reflect the 20-second
offset (or adjust plusSeconds to 10 if you intended 10s) so the comment and the
SignedJWT creation in the test are consistent.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@esignet-service/src/main/java/io/mosip/esignet/advice/DpopValidationFilter.java`:
- Around line 294-303: The iat past-bound check in DpopValidationFilter (using
claims.getIssueTime()) omits the clock-skew tolerance; update the past
comparison to subtract both maxDPOPIatAgeSeconds and maxClockSkewSeconds from
Instant.now() (i.e., use Instant.now().minusSeconds(maxDPOPIatAgeSeconds +
maxClockSkewSeconds) or equivalent) so the iat is allowed a skew window just
like the future-bound check that uses plusSeconds(maxClockSkewSeconds).

In
`@esignet-service/src/test/java/io/mosip/esignet/advice/DpopValidationFilterTest.java`:
- Around line 372-383: The test reuses the same MockHttpServletRequest and
MockHttpServletResponse which causes multiple DPoP headers and leftover response
state; for the second scenario in DpopValidationFilterTest (the block that
builds/signs the expired iat JWT and calls filter.doFilterInternal), create and
use a fresh request and response (or explicitly remove existing DPoP headers and
reset response) before adding the new DPoP header so that
DpopValidationFilter.getDpopHeader() sees only one header and the response
status starts from a clean state; keep using the same filter and filterChain
mocks but verify interactions (e.g., verify(filterChain, never()).doFilter(...))
against the fresh request/response.

---

Nitpick comments:
In `@esignet-service/src/main/resources/application-default.properties`:
- Around line 25-28: Update the properties comment to correctly state that
mosip.esignet.dpop.clock-skew applies to the iat, nbf and exp claims (as
enforced by DefaultJWTClaimsVerifier.setMaxClockSkew()) and note that this is
used as the future-iat tolerance (maxClockSkewSeconds) in the custom filter,
while mosip.esignet.dpop.iat.max-age-seconds controls past-age tolerance for
iat; change the single-line comment above the properties to reflect these three
affected claims and the relationship between clock-skew (future tolerance) and
iat.max-age-seconds (past tolerance).

In
`@esignet-service/src/test/java/io/mosip/esignet/advice/DpopValidationFilterTest.java`:
- Around line 340-358: Update the inaccurate inline comment in the test method
testDpopHeader_withIatOutsideTimeLimit_thenFail: the comment currently says "iat
set 10 seconds in the future" but the code sets issueTime to
Instant.now().plusSeconds(20); change the comment to reflect the 20-second
offset (or adjust plusSeconds to 10 if you intended 10s) so the comment and the
SignedJWT creation in the test are consistent.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 957a457e-104a-40bf-b67e-ea165de010a9

📥 Commits

Reviewing files that changed from the base of the PR and between b17c19d and abf96aa.

📒 Files selected for processing (3)
  • esignet-service/src/main/java/io/mosip/esignet/advice/DpopValidationFilter.java
  • esignet-service/src/main/resources/application-default.properties
  • esignet-service/src/test/java/io/mosip/esignet/advice/DpopValidationFilterTest.java

Signed-off-by: Sachin Rana <sacrana324@gmail.com>
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.

🧹 Nitpick comments (1)
esignet-service/src/main/java/io/mosip/esignet/advice/DpopValidationFilter.java (1)

305-308: Catch block still re-catches InvalidDpopHeaderException causing redundant logging.

The log message improvement addresses part of the past review feedback, but the catch block still intercepts InvalidDpopHeaderException thrown from within the try block (lines 284, 292, 299, 303). This results in double logging—first the specific message (e.g., "Missing htu claim"), then "DPOP jwt claim validation failed".

♻️ Proposed fix to rethrow InvalidDpopHeaderException without re-logging
-        } catch (Exception e) {
-            log.error("DPOP jwt claim validation failed", e);
+        } catch (InvalidDpopHeaderException e) {
+            throw e;
+        } catch (Exception e) {
+            log.error("DPoP JWT claim validation failed", e);
             throw new InvalidDpopHeaderException();
         }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@esignet-service/src/main/java/io/mosip/esignet/advice/DpopValidationFilter.java`
around lines 305 - 308, The catch-all in DpopValidationFilter currently
re-catches InvalidDpopHeaderException and logs it again; update the exception
handling so InvalidDpopHeaderException is caught and immediately rethrown
without logging (e.g., add an explicit catch(InvalidDpopHeaderException) {
throw; }) and keep the generic catch(Exception e) to log and wrap other
unexpected exceptions thrown during methods like
validateDpopClaims/validateHtu/validateHtm referenced in the class; this ensures
the specific validation exceptions (InvalidDpopHeaderException) are not
double-logged while still handling other errors.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@esignet-service/src/main/java/io/mosip/esignet/advice/DpopValidationFilter.java`:
- Around line 305-308: The catch-all in DpopValidationFilter currently
re-catches InvalidDpopHeaderException and logs it again; update the exception
handling so InvalidDpopHeaderException is caught and immediately rethrown
without logging (e.g., add an explicit catch(InvalidDpopHeaderException) {
throw; }) and keep the generic catch(Exception e) to log and wrap other
unexpected exceptions thrown during methods like
validateDpopClaims/validateHtu/validateHtm referenced in the class; this ensures
the specific validation exceptions (InvalidDpopHeaderException) are not
double-logged while still handling other errors.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 72eeb2cc-b935-493a-8205-8b23630827ea

📥 Commits

Reviewing files that changed from the base of the PR and between abf96aa and ef3640c.

📒 Files selected for processing (3)
  • esignet-service/src/main/java/io/mosip/esignet/advice/DpopValidationFilter.java
  • esignet-service/src/main/resources/application-default.properties
  • esignet-service/src/test/java/io/mosip/esignet/advice/DpopValidationFilterTest.java
🚧 Files skipped from review as they are similar to previous changes (1)
  • esignet-service/src/test/java/io/mosip/esignet/advice/DpopValidationFilterTest.java

Signed-off-by: Sachin Rana <sacrana324@gmail.com>
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