DirtyChai, a JVM security framework built on JGDMS, introduces a sealed Subject hierarchy with two distinct identity types: WorkerSubject (process-level, SPIFFE-backed) and UserSubject (per-request, JWT/OIDC). WorkerSubject is baked into every ProtectionDomain at class load time and is ambient across all permission checks, while UserSubject travels via ScopedValue and is bound per request using Subject.callAs(). SPIFFE workload identity replaces traditional keystores — short-lived X.509 SVIDs are managed by a SPIRE agent, rotated automatically without JVM restarts. During a dispatched RPC, up to three identity layers coexist: the local process worker, the remote client's process context (verified via SHA-256 digest), and the per-request user identity. A single call can carry up to 16 user Subjects. The design deliberately separates identity from privilege, retiring doAs/doAsPrivileged in favor of callAs plus explicit doPrivileged boundaries.
Questions this post answers
What is the difference between Subject.callAs() and Subject.doAs() in Java JAAS and why is doAs being deprecated?
callAs() binds identity on a ScopedValue and that identity survives doPrivileged boundaries, keeping who-you-are and what-privileges-code-runs-with orthogonal. doAs() couples them: used merely to run privileged, it also drops the user by rebinding the subject and suppressing the enclosing one. Dropping the user becomes an unintended side effect of a code boundary rather than a deliberate choice. doAs and doAsPrivileged are retained only for legacy JAAS and Kerberos GSS interop. Java teams migrating JAAS-based auth track these API shifts on daily.dev before they hit production.
How does SPIFFE workload identity work without keystores in a Java JVM service?
A SpiffeCredentialManager opens the SPIRE Workload API socket on startup and populates an in-memory Subject with the current X.509 certificate and private key — no filesystem keystore or PKCS#12 files. The default SVID lifetime is about one hour. Credentials rotate automatically when the SVID nears expiry, triggering a policy refresh, all without JVM restarts or manual certificate renewal. Engineers replacing keystore-based mTLS with SPIFFE find the tradeoffs covered on daily.dev.
How does DirtyChai handle unverifiable ProtectionDomains received over the JERI wire in version 23?
Version 23 of AccessControlContextSerializer stopped stripping unverifiable domains before transport. Instead, unverifiable domains are counted as anonCount and reconstructed as anonymous placeholder ProtectionDomains on the receiving JVM — their permission ceilings are preserved without asserting a specific identity. Earlier versions stripped them, which was recognized as an implicit privilege escalation. Developers working with JGDMS serialization changes watch for breaking shifts like this on daily.dev.
15.6K Impressions2 Comments