00.76.00
Release date: 2026-06-25 Previous release: 00.75.20 Maven coordinates (parent):
com.svenruppert.jsentinel:jSentinel-parent:00.76.00Full changelog: GitHub release v00.76.00
Before 00.76, bearer tokens were opaque strings and every RestSubjectResolver
re-implemented signature / exp / iss / aud checks. Now JWT validation is a
first-class, hardened building block.
Headline — validate a JWT in three config lines
RestSecurity.bootstrap()
.mode(SecurityBootstrapMode.PRODUCTION)
.jwt(j -> j
.jwksUri(URI.create("https://idp.example/.well-known/jwks.json"))
.algorithmProfile(AlgorithmProfile.STRICT_MODERN)
.issuer("https://idp.example/")
.audience("api.example"))
.install();A RestSubjectResolver then validates via JSentinelServiceResolver.findJwtValidator()
and binds an OidcAccessToken.fromValidated(...).
What’s new
jSentinel-jwt— the new opt-in module: a Nimbus JOSE+JWT-backedNimbusJwtValidator, anHttpJwksClientwith a disciplined cache,NimbusJwtValidatorFactoryand aJwtDiagnosticContributor. The only module on the reactor with a JOSE library on the classpath.- JOSE-free core SPIs (
jSentinel-core/jwt/api) —JwtValidator,ValidatedJwt, a sealedJwtValidationError,JoseHeader,JwsAlgorithm,AlgorithmAllowList/AlgorithmProfile,ClaimExpectations,ClockSkewPolicy,JwksClient,JwtValidatorFactory/JwtValidatorSpec— 12Result-based types, sealed errors with kebab-case codes. .jwt(...)fluent bootstrap (jSentinel-dx) — adapter-symmetric across Vaadin / REST / Standalone; the DX layer discovers the Nimbus factory viaServiceLoaderand never compiles against a JOSE type.- Inbound OIDC —
OidcInboundTokenValidatorinjSentinel-propagation-oidc(core SPI only; the JOSE-enforcer ban stays intact). - Events — four
JSentinelEventtypes (JwtValidationSucceeded/Failed,JwksRefreshed/RefreshFailed), non-secret payloads only. - Demo — a
demo-rest/api/jwt/demoroute with a NimbusJwtIssuerStub, end to end.
Security posture
A mandatory algorithm allow-list (no implicit allow-all) with hard
algorithm-confusion defence — alg:none, HMAC-with-asymmetric-key and
alg/key-family mismatch are all rejected; asymmetric-only (RS / PS / ES /
EdDSA). Strict iss exact-match + aud intersection. The JWKS client cannot
be turned into a DoS against the IdP — TTL from Cache-Control: max-age,
single-flight refresh on a kid miss, a 30 s negative cache and a 1 MiB body
cap. EdDSA runs on the JDK’s native provider (no Google Tink). All vectors are
adversarially tested with no mocks (real Nimbus issuers, a real JDK
HttpServer JWKS stub).
Additivity
Additive over 00.73 / 00.74 / 00.75. The only core changes are additive:
OidcAccessToken gains a fifth optional validated component (the
TokenCredential permits clause is unchanged), the jwt/api package is new,
and JSentinelServiceResolver gains a find/setJwtValidator pair. No
00.74/00.75 STRICT code is promoted; the new STRICT codes
(jwt/no-algorithm-allow-list, jwks/uri-not-https, …) only fire when
.jwt(...) is actually used. All 00.76 public types carry
@ExperimentalJSentinelApi.
What it does not do
No OAuth2 flows (00.77), no OIDC discovery / ID-token semantics (00.78), no JWE / DPoP / vendor profiles (00.79), no JWT signing, no symmetric (HMAC) JWT.
Quality
jSentinel-jwt gets its first PIT baseline at 66 % (76/116); the survivors
cluster in JWKS-cache timing/guard branches. Every touched 00.71–00.75 module
retains its baseline by construction (00.76 only adds tested code and additive
fields). Full-reactor clean install green across all 40 modules; entry + exit
production reviews executed with all mandatory findings fixed in-cycle. No
mocks.
Migration
None. The JWT stack is opt-in; apps that don’t call .jwt(...) pull no new
dependency. Just bump the version to 00.76.00.