Skip to content
Flag of Europe
Made in the European Union · Independently built · Released under EUPL 1.2
jSentinel iris — green eye framed by bracket lids; logo of the project jSentinel iris — green eye framed by bracket lids; logo of the project

jSentinel Lightweight Security for Core Java, REST and Vaadin.

Pluggable authentication, authorization, and annotation-driven protection — wired through Java SPI, no Spring or Jakarta required.

jsentinel.eu

Capabilities

Annotation-Driven, Three Adapters

Same @RequiresRole / @RequiresPermission annotations protect Vaadin views (navigation listener), REST handlers (filter), and plain Java services (Secured.wrap(…) dynamic-proxy). One scanner, three call sites.

Framework-Neutral Core

security-core has no Vaadin, Servlet, or REST-framework dependencies. Adapters map a single decision model to navigation or HTTP status.

Java SPI by Design

Authentication, authorization, audit, action, login-attempt, session-policy, password-hashing, logout — every contract pluggable via META-INF/services/. One SecurityServiceResolver resolves them all.

Hardened First-Run Bootstrap

The first administrator is created via a one-time token. POSIX 0600 file, atomic creation, PBKDF2-HMAC-SHA256, never logged, never echoed.

Granted / 401 / 403 — That's It

AuthorizationDecision collapses to three outcomes. REST adapters map them to status codes; Vaadin maps them to navigation. Error bodies are short and generic.

Four Reference Demos

Standalone Vaadin (demo-vaadin), JDK-only REST server + CLI (demo-rest), two-tier setup (demo-vaadin-rest-client), and a pure Core-Java CLI library (demo-standalone) — one annotation set, four call shapes. Both Vaadin demos ship a role-admin UI, user CRUD, and an audit-log view.

Production Hardening

SecurityAuditService with 27 sealed event types and a ring-buffer sink. LoginAttemptPolicy brute-force protection with 429 + Retry-After and lockout UI. SessionPolicy with idle/absolute lifetime and session-id rotation after login.

Method Security, Two Ways

Enforce @RequiresRole / @RequiresPermission / @RequiresPolicy on plain Java methods — a compile-time annotation processor generates <Type>Secured wrappers, or SecuredProxy.wrap(…) at runtime. Both route through one SecurityEnforcer.

Policy API

Beyond roles and permissions: a typesafe policy builder, @RequiresPolicy, and a sealed PolicyDecision (Allowed / Denied / StepUpRequired) with resource-aware, owner-or-admin style checks.

Multi-Tenancy + Active-Session Role Refresh

TenantId scopes every store key. SecurityVersion drift detection refreshes roles for live sessions — revoke a role and the next request is rejected (Vaadin reroute / REST 401), no waiting for expiry.

Store-Agnostic Persistence

11 small store SPIs with in-memory defaults, an Eclipse Store reference backend, and a contract testkit. Swap to durable storage with one dependency — no code change. Redis / JDBC are drop-in.

Credential Hardening + Compliance

A standards-aligned credential stack: Argon2id / bcrypt / scrypt, post-KDF HMAC pepper, breached-password checks (Have I Been Pwned), abuse detection — mapped to OWASP ASVS V2, NIST SP 800-63B and 40 CWE classes.

Multi-Session Logout & Action Audit

LogoutService.logout(SubjectId, LogoutScope) signs out one or every session. ActionAuthorizationService emits an ActionDenied audit event on every denial — no manual instrumentation.

Mutation-Tested Library

Line coverage tells you tests executed the code.
Mutation testing changes the bytecode at runtime and asks the harder question: did the tests catch the change?

Line coverage
Code ran during a test
Easy to game
vs.
Mutation coverage
Tests detected a real bug
What you actually want

A surviving mutation is a real gap. Here's where the library stands.

security-core
87%
mutation coverage
1901 of 2196 mutations killed · 956 tests
Mutation
87%
security-rest
95%
mutation coverage
86 of 91 mutations killed · 71 tests
Mutation
95%
security-standalone
97%
mutation coverage
33 of 34 mutations killed · 30 tests
Mutation
97%
security-vaadin
79%
mutation coverage
242 of 305 mutations killed · 172 tests
Mutation
79%
security-processor
82%
mutation coverage
23 of 28 mutations killed · 100% line coverage
Mutation
82%
security-persistence-eclipsestore
70%
mutation coverage
231 of 328 mutations killed · 104 tests
Mutation
70%
security-crypto-bc · new in 00.71
61%
mutation coverage
110 of 181 mutations killed · first PIT pass, uplift tracked for 00.73
Mutation
61%
security-credentials-hibp · new in 00.71
53%
mutation coverage
39 of 74 mutations killed · first PIT pass, uplift tracked for 00.73
Mutation
53%

Mutation coverage = killed mutations / total mutations. Mutation testing rewrites the bytecode and asks whether the tests catch the change — a far harder bar than line coverage. These are the per-module figures as of the latest 00.72.00 release. The mature library modules carry the production guarantee; the two credential modules added in 00.71 are at a first PIT pass with uplift tracked for 00.73. The seven 00.72 developer-experience modules and the full per-module mutator breakdown are on the Architecture page.