Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
feat: add DPoP sender-constrained token support (RFC 9449) #732
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
feat: add DPoP sender-constrained token support (RFC 9449) #732
Changes from all commits
2472b654eaefb028dad70File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
There are no files selected for viewing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Intentional — this matches go-sdk's behavior (descope/go-sdk#737 uses
diff >= dpopIATWindow), which rejects at the boundary (exactly ±window). The window is exclusive on both ends by design: a proof at exactly +60 s or -5 s is stale/future and should be rejected. No change needed.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🟡 MEDIUM: No
jtireplay protection. RFC 9449 §11.1 recommends servers track previously-seenjtivalues (scoped per-client) to prevent DPoP proof replay within theiatwindow. As implemented, an attacker who captures a valid DPoP proof can replay it for up to ~60s against the samehtm+htu+session token.A stateless SDK can't track
jtiitself (needs a shared store), but this responsibility should be called out explicitly in the README and thevalidateDPoPJSDoc so consumers know they must layer replay tracking on top. Otherwise developers will reasonably assumevalidateDPoPis sufficient for full RFC 9449 compliance.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Deferred — jti replay protection requires server-side storage which a stateless SDK cannot provide. This matches the go-sdk reference implementation (descope/go-sdk#737). Added a
@noteto thevalidateDPoPProofJSDoc and a callout block in the README documenting the gap and directing integrators to implement a server-side jti store (e.g. Redis with TTL ≈ iat window) if replay protection is required.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🟡 MEDIUM: No test file (
lib/dpop.test.ts) exists for this module. This is ~240 lines of security-critical validation code (JWS verification, JWK thumbprint binding,ath/htm/htu/iatchecks) covering many failure paths — and a regression here either silently accepts forged proofs or breaks all DPoP-bound sessions.At minimum, please add tests for: valid proof acceptance, each rejection path (bad
typ, badalg, symmetric key, private key, signature mismatch, missing/wrongjti/htm/htu/iat/ath,iatoutside both windows, JWK thumbprint mismatch), the non-DPoP-bound no-op path, and thehtunormalization edge cases (default ports, query/fragment, casing).Uh oh!
There was an error while loading. Please reload this page.