Skip to content
Flag of Europe
Made in the European Union · Independently built · Released under EUPL 1.2

00.79.10

Available on Maven Central. Etappe 2 of the 00.79 hardening line: DPoP sender-constrained tokens, replay-protection stores and OIDC logout-hardening. Additive — all new types are @ExperimentalJSentinelApi (own soak window); the Etappe-1 stable JWT / OAuth2 / OIDC surfaces are unchanged. The current release is 00.79.41.

Release date: 2026-06-27 Previous release: 00.79.00 Maven coordinates (parent): com.svenruppert.jsentinel:jSentinel-parent:00.79.10 Full changelog: GitHub release v00.79.10

Three security blocks, building on the Etappe-1 vendor profiles + Stable-API promotion.

Replay-protection stores

Two persistence-neutral SPIs in jSentinel-core: JtiStore (single-use jti — backs DPoP-proof and logout-token replay protection) and NonceStore (per-request-key, single-use, TTL-checked). InMemoryJtiStore is a bounded sliding window that, on overflow, evicts the soonest-to-expire entry — never the least-recently-used (an LRU policy would let an attacker flood the store to evict a victim’s still-live jti and replay a captured proof; same class as the 00.75.20 R012 fix). Single-JVM defaults; a multi-node deployment plugs a shared store.

DPoP — sender-constrained tokens (RFC 9449)

New opt-in module jSentinel-dpop:

  • DpopProofGenerator signs an outbound dpop+jwt proof (embedded public JWK; jti / htm / htu / iat, plus ath when bound to an access token).
  • NimbusDpopProofValidator verifies the signature against the embedded key, enforces an algorithm allow-list (rejects none / private / symmetric header keys), checks htm / htu (normalised) / iat freshness (too-old and future rejected) / ath (constant-time), and enforces single-use jti via the JtiStore. It returns the RFC 7638 key thumbprint so the caller can bind a DPoP-confirmed access token (cnf.jkt). The thumbprint is computed before the jti is recorded, so a failure can’t consume a one-time jti.
  • Sealed, leak-free DpopValidationError (proof-malformed / signature-invalid / htm-mismatch / htu-mismatch / proof-expired / replay / ath-mismatch); a DpopKeyStore SPI holds per-target signing keys.

OIDC logout-hardening

Back-Channel + Front-Channel Logout 1.0 (API in jSentinel-core, impls in jSentinel-identity-oidc):

  • DefaultLogoutTokenValidator composes a JwtValidator and adds the §2.4 checks: the back-channel-logout events member required, nonce must be absent (stops an ID token being replayed as a logout token), sub/sid present, jti required + single-use via JtiStore.
  • BackChannelLogoutReceiver is pure token-in / outcome-out — it dereferences no URL from the token, so no SSRF (§2.6) — and terminates RP sessions via a SessionRegistry SPI.
  • FrontChannelLogoutEndpoint checks iss against the trusted issuer first — a forged issuer is a silent no-op (no spoofed force-logout).

Exit-review

A two-pronged adversarial review fixed three findings before ship: LRU→soonest- to-expire eviction (R-EXIT-1), thumbprint-before-jti (R-EXIT-2), and jti now required on logout tokens (R-EXIT-3). No mocks — DPoP round-trips run real RSA/EC Nimbus signing; logout tests use real RSA-signed logout tokens. jSentinel-dpop first PIT pass: 63 % (57/91).

Migration

None. Additive. Add jSentinel-dpop to sign/validate DPoP proofs; wire BackChannelLogoutReceiver behind your backchannel_logout_uri. Just bump the version to 00.79.10.