Release notes¶
Notable changes to javalin-security. This changelog follows
Keep a Changelog; versioning follows
Semantic Versioning.
[2.0.0] - Unreleased¶
Current version: 0.2.0.
Nothing has shipped yet, so this is the first release. It is versioned 2.0.0 because the
extension API went through several breaking redesigns before release: concrete-identity classes
were replaced with a generic-on-identity design, then the generic was dropped in favour of the
Identity interface, and roles were moved off Identity onto Authentication (carried by
scheme-specific *Details records). Identity types are brought by the caller and read back
with ctx.identity<T>() — an unchecked cast, like ctx.attribute<T>().
Roles owned by Authentication, not Identity¶
Identityno longer hasroles. It keepsnameonly. Roles are supplied toAuthentication.authenticated(identity, roles)by each extension.- Scheme-specific
*Detailsrecords carry roles alongside identity: BasicUserDetails(identity, encodedPassword, roles)— replaces corePasswordCredentialsand lives in the basic-auth module.ApiKeyDetails(identity, roles)—ApiKeyLookupnow returnsApiKeyDetails?.OpaqueTokenDetails(identity, expiresAt, roles)— renamed fromTokenRecord.SessionDetails(identity, roles)—SessionManager.create/validatetake/return it.- JWT keeps
JwtRolesMapper(input isDecodedJwt).identityMapperandrolesMappermay be used together; the built-inJwtidentity no longer carries roles. - Migration:
// Before
data class User(override val name: String, override val roles: Set<RouteRole>) : Identity
PasswordCredentials(User("alice", setOf(Role.USER)), "pw")
sessionManager.create(ctx, User("alice", setOf(Role.USER)))
// After
data class User(override val name: String) : Identity
BasicUserDetails(User("alice"), "pw", setOf(Role.USER))
sessionManager.create(ctx, SessionDetails(User("alice"), setOf(Role.USER)))
Extension API — no generic on the factory¶
- No
<I>on the factory.basicAuth { },apiKey { },opaqueToken { },session { }, andjwt { }are all non-generic. ConfigureuserLookup/lookup/sessionManager/identityMapperwith your ownIdentitytype; read it back withctx.identity<YourType>(). - Non-generic SPI types.
BasicUserDetails,ApiKeyDetails,OpaqueTokenDetails,SessionDetails,UserLookup,ApiKeyLookup,OpaqueTokenLookup,JwtIdentityMapper,SessionManager, andHttpSessionManagerare all non-generic — their identity field is typed asIdentity. HttpSessionManagerSerializable check. The default session manager now checksdetails.identity is Serializableat create time and throwsIllegalArgumentExceptionwith a descriptive message when it isn't — the same guarantee the previous compile-time bound provided, surfaced eagerly atSessionManager.create(...)instead of at replication time.- Single
jwt { }overload. The genericjwt<I> { }overload (and the JavaJwtSecurity.jwtWithIdentity(...)companion) is gone; setidentityMapperon the same non-genericjwt { }block to map verified tokens to your own domain identity. The default path (noidentityMapper) still attaches the built-inJwtidentity.
Basic Auth encoded password is not on the identity¶
UserLookupreturnsBasicUserDetails(identity + encoded password + roles kept separate), so the encoded password used for verification is never reachable viactx.identity<I>().
Session¶
- Ships a default
HttpSessionManager—session { }works with zero configuration. - Session create/invalidate is the caller's responsibility: keep a reference to your
SessionManagerand callcreate/invalidatefrom login/logout handlers with aSessionDetailspayload. The strategy only validates sessions on each request. - Default
HttpSessionManagerrotates the session id on create for session-fixation defense.
Added¶
- Core (
javalin-security): HTTP and WebSocket guards (installed with the plugin),security { }configuration,authentication()/identity()/identityOrNull()accessors,AuthenticationStrategy.sync/.asyncfactory helpers. - Authentication SPI: sync and async strategies,
AuthenticationResult,Identity, unauthorized handlers. - Authorization: built-in rules, rule tables,
Anyone, deny-by-default fallback, path patterns (Javalin syntax), CORS preflight bypass. - WebSocket: Origin allow-listing at upgrade.
- Basic Auth (
javalin-security-basic-auth):basicAuth { }, user lookup returningBasicUserDetails, password encoder, optionalWWW-Authenticatechallenge. - API Key (
javalin-security-api-key):apiKey { }, key lookup returningApiKeyDetails, header/query/cookie resolvers. - Opaque Token (
javalin-security-opaque-token):opaqueToken { }, token lookup returningOpaqueTokenDetails, expiry validation, optionalWWW-Authenticate: Bearerchallenge. - Session (
javalin-security-session):session { }with a defaultHttpSessionManager,SessionDetails, session-id rotation on create, runtimeSerializablecheck on the default manager. Callers wireSessionManager.create/invalidatethemselves. - JWT (
javalin-security-jwt): singlejwt { }factory — defaultJwtidentity, opt into your own viaidentityMapper; decoder SPI, key sources, roles mapping (combinable withidentityMapper), optional bearer challenge. - Decoder adapters: Nimbus and Auth0 (JWKS caching, RSA / EC / HMAC).
- Java interoperability across modules.
Compatibility¶
- Java 17+, Javalin 7.2.x, Kotlin 2.0+.
Pre-release
While the version is 0.2.0, the public API may still change before the
first stable release.