Join our Newsletter — 33% off our NHI Course
Home› Guides› Jakarta EE Security: Authentication, Identity Stores and Authorisation…
Guide Application Security

Jakarta EE Security: Authentication, Identity Stores and Authorisation Done Right

← All guides
By NHI Mgmt Group, edited by Lalit Choda Updated 8 November 2026 12 min read
On this page

Enterprise Java applications often get authentication right in one place and wrong in three others: an uncovered HTTP method, a password hash at the specification's minimum work factor, or an OpenID Connect client secret compiled into an annotation. Jakarta Security is the standard, portable API for authentication and identity in Jakarta EE, sitting on top of the lower-level Jakarta Authentication and Jakarta Authorization specifications. This guide explains how those pieces fit together in Jakarta EE 11 (Jakarta Security 4.0), how to choose and configure the built-in authentication mechanisms and identity stores, how to keep administrative and role logic tight, how to handle the service credentials the configuration needs, and what to log. It is written for Java developers, application architects and AppSec engineers working on GlassFish, WildFly, JBoss EAP, Open Liberty, Payara or any other compatible runtime. Spring applications are covered in the Java and Spring Security Guide.

This is an independent guide from NHI Mgmt Group, based on the Eclipse Foundation's Jakarta EE public documentation as of November 2026. It is not sponsored or reviewed by the Eclipse Foundation. Product features change, so confirm settings against the Jakarta EE current documentation.

Key takeaways

  • Jakarta Security is the layer to code against. Use HttpAuthenticationMechanism, IdentityStore and SecurityContext instead of server-specific realm APIs, and drop down to Jakarta Authentication only for custom mechanisms.
  • Raise the PBKDF2 work factor. The built-in Pbkdf2PasswordHash defaults to 2,048 iterations of PBKDF2WithHmacSHA256; OWASP recommends 600,000 for that algorithm.
  • Never hard-code secrets in annotations. The OpenID Connect clientSecret and LDAP bindDnPassword are plain annotation strings; resolve them through expressions from configuration or a vault.
  • Close uncovered HTTP methods. A security constraint that lists only GET and POST leaves PUT, DELETE and others unprotected unless <deny-uncovered-http-methods/> is set.
  • Logging is the server's job, not the specification's. Jakarta Security defines no audit format, so plan login, failure and role-change logging in the runtime and the application.

How identity and access work in Jakarta EE

Jakarta EE 11 requires Java SE 17 or later. The release page lists Jakarta Security 4.0, Jakarta Authentication 3.1 and Servlet 6.1 in the Web Profile, Jakarta Authorization 3.0 under the full Platform, and Jakarta Annotations 3.0 (which provides @RolesAllowed) in the Core Profile. Each layer has a distinct job.

SpecificationVersion (EE 11)RoleWhat developers touch
Jakarta Security4.0Portable, CDI-based authentication and identity APIHttpAuthenticationMechanism, IdentityStore, SecurityContext, built-in mechanism and store annotations
Jakarta Authentication3.1Low-level SPI that connects authentication mechanisms to the containerServerAuthModule for custom, non-HTTP or unusual mechanisms
Jakarta Authorization3.0Container authorisation contract and policy providersRarely touched directly; 3.0 allows per-application policy providers registered programmatically
Servlet6.1Web security constraints, sessions, cookiesweb.xml security-constraint, @ServletSecurity, session cookie configuration
Jakarta Annotations3.0Declarative role checks on beans@RolesAllowed, @PermitAll, @DenyAll

Version 4.0 added a handler API for using several authentication mechanisms in one application, CDI qualifiers on the built-in mechanisms, and an in-memory identity store, and removed references to the Java SecurityManager. The compatible implementation is Eclipse Soteria. Version 5.0 for Jakarta EE 12 is under development, so check the specification page before relying on newer features.

Built-in authentication mechanisms

AnnotationUse it forSecurity notes
@BasicAuthenticationMechanismDefinitionInternal tools and machine clients during migrationCredentials on every request; only over TLS; no logout; vulnerable to password spraying (T1110.003)
@FormAuthenticationMechanismDefinitionClassic server-rendered login pagesUses @LoginToContinue, defaults /login and /login-error; protect the form with CSRF controls and rate limiting
@CustomFormAuthenticationMechanismDefinitionLogin pages backed by a Jakarta Faces or REST call that invokes SecurityContext.authenticate()Lets the application add MFA or lockout logic before authentication completes
@OpenIdAuthenticationMechanismDefinitionSingle sign-on with an external OpenID Connect providerDefaults: response_type=code, scopes openid, email and profile, nonce on, state validated, redirect URI ${baseURL}/Callback

Built-in identity stores

  • Database store: @DatabaseIdentityStoreDefinition takes a dataSourceLookup (default java:comp/DefaultDataSource), a callerQuery that returns the password hash and a groupsQuery. Hashing defaults to Pbkdf2PasswordHash.
  • LDAP store: @LdapIdentityStoreDefinition takes a URL, an optional bindDn and bindDnPassword, caller and group search bases and filters, maxResults (default 1,000) and readTimeout (default 0, meaning no timeout). See the LDAP Security Deep Dive Guide.
  • In-memory store: @InMemoryIdentityStoreDefinition holds users in the annotation. The specification says it is provided for testing, debugging and demos and is not generally advised for production.
  • Ordering: stores run in priority order (lower first; LDAP defaults to 80, database to 70), and useFor separates credential validation from group lookup, so one store can authenticate and another can supply groups.

Admin roles and privileged access

Jakarta EE has no built-in "administrator": privilege is whatever role names the application declares and maps to groups. That makes role design and mapping the main privileged access control.

  • Keep role names few and explicit: declare administrative roles separately (for example app-admin, billing-admin) rather than reusing a broad admin group from the directory. SecurityContext.getAllDeclaredCallerRoles(), added in 4.0, lists the static roles a caller holds and is useful for access reviews and debugging.
  • Map groups to roles deliberately: with the OpenID Connect mechanism, groups come from the groups claim and the caller name from preferred_username by default. Confirm that your provider issues those claims only from authoritative sources, and do not map a group that users can join themselves.
  • Enforce at every layer: use URL constraints for coarse protection, @RolesAllowed on bean methods for business operations, and object-level checks in code for data ownership. A role check at the servlet layer does not protect a REST resource reached through another path. See the Broken Access Control Prevention Guide.
  • Default deny on beans: put @DenyAll at class level on sensitive beans and open individual methods with @RolesAllowed, so a new method is protected by default.
  • Use step-up for dangerous actions: a custom form mechanism or an HttpAuthenticationMechanism can require re-authentication or an MFA claim before admin operations such as role changes or exports.
  • Separate the server's own admins: application roles are distinct from application server management users. Harden the runtime's management interface separately; see the JBoss EAP and WildFly Hardening and the Apache Tomcat Hardening Guide.

Integrations, API tokens and service accounts

A Jakarta Security configuration typically depends on three non-human credentials: the database account behind the identity store's data source, the LDAP bind account and the OpenID Connect client secret. Each is a long-lived secret held by the application.

CredentialWhere it is configuredRiskControl
OpenID Connect client secretclientSecret on @OpenIdAuthenticationMechanismDefinitionThe specification's own Javadoc strongly recommends setting it through an expression so the value is not hard-codedUse an expression such as ${openIdConfig.clientSecret} backed by a CDI bean that reads a vault or MicroProfile Config source
LDAP bind passwordbindDnPassword on @LdapIdentityStoreDefinitionPlain string in source; bind accounts often have broad directory read rightsRead-only bind account restricted to the search bases used; secret injected at runtime; LDAPS only
Identity store database accountData source in the server configurationRead access to every password hashDedicated account with SELECT on the user and group tables only; password from the server's credential store
Remember-me tokens@RememberMe with an application RememberMeIdentityStoreBearer token in a cookie (default name JREMEMBERMEID, max age 86,400 seconds)Store only a hash of the token server side, rotate on use, revoke on password change
  • Scan for leaks: annotation values end up in source control and in compiled classes. Scan both. See the Secrets Management Guide.
  • Machine clients: for service-to-service calls, prefer OAuth 2.0 client credentials or mutual TLS validated by a custom mechanism over Basic authentication with a shared service password. See the OAuth 2.0 and OpenID Connect Guide and the Java Keystores Guide.
  • Token refresh: tokenAutoRefresh is off by default, so sessions keep running on the original authentication until the session ends. Decide explicitly whether access token expiry should end or refresh the session.

Logging and detection

Jakarta Security does not define audit events. The runtime (for example Elytron audit logging in WildFly and JBoss EAP) and your own code must produce them. A practical approach is to log from a CDI decorator or wrapper around your HttpAuthenticationMechanism and from role-change code paths.

EventWhere to capture itRelated technique
Authentication success and failure with caller name, mechanism and source IPServer security audit log or mechanism wrapperT1110 Brute Force, T1078 Valid Accounts
Many failures across many usernames from one sourceSIEM correlation on failure eventsT1110.003 Password Spraying
OpenID Connect callback failures (state mismatch, invalid token)Mechanism logsLogin CSRF or token injection attempts
Remember-me token reuse from a new device or IPApplication RememberMeIdentityStoreT1539 Steal Web Session Cookie
403 responses on unusual HTTP methodsAccess logsProbing for uncovered methods
Admin role grants and changesApplication audit trailT1078 Valid Accounts
Exploit-style payloads against public endpointsReverse proxy, WAFT1190 Exploit Public-Facing Application

Never log passwords, tokens, the remember-me cookie or the full OpenID Connect callback query string, which contains the authorisation code.

Metrics that show it is working

  • Hash strength: share of stored hashes at the target iteration count (rehash on next login until 100 percent).
  • Secret hygiene: number of literal secrets found in annotations or configuration by scanning (target: zero).
  • Constraint coverage: applications with deny-uncovered-http-methods set and no container warnings about uncovered methods.
  • Authentication mix: share of logins through OpenID Connect versus local password stores.
  • Failure rate: authentication failures per hour and per source, with alert thresholds.

Hardening baseline

AreaSettingDetail
Password hashinghashAlgorithmParameters on the database storeSet Pbkdf2PasswordHash.Iterations=600000 with PBKDF2WithHmacSHA256 (or 220,000 with SHA512); defaults are 2,048 iterations, 32-byte salt, 32-byte key. Hashes are stored as algorithm:iterations:salt:hash, so old hashes still verify while you upgrade
HTTP methods<deny-uncovered-http-methods/> in web.xmlThe container must reject uncovered methods with 403
Transporttransport-guarantee CONFIDENTIAL or @ServletSecurity(@HttpConstraint(transportGuarantee = TransportGuarantee.CONFIDENTIAL))Forces HTTPS for protected resources
Session cookiesession-config cookie http-only and secure, tracking mode COOKIEAvoids session IDs in URLs; see the Cookie Security Guide
Session fixationNew session ID after loginCall HttpServletRequest.changeSessionId() in custom flows if the container does not
Remember-mecookieSecureOnly and cookieHttpOnly true (defaults), shorter cookieMaxAgeSeconds for sensitive appsDefault lifetime is one day
OpenID ConnectKeep useNonce true; exact redirect URI registered at the provider; secret via expressionDefaults are sound; do not disable nonce for convenience
LDAPldaps:// URL, non-zero readTimeout, scoped search basesDefault read timeout is unlimited
Identity storesNo in-memory store in production buildsExclude test configuration from release artefacts
Expression LanguageNever pass user input into EL evaluationEL injection leads to code execution; see the Java Secure Coding Guidelines Guide

Phased rollout

  1. Inventory: list each application's mechanism, identity stores, declared roles, security constraints and the credentials it holds.
  2. Quick wins: add deny-uncovered-http-methods, transport guarantees and cookie flags in a test environment; read the container's deployment log for uncovered method warnings.
  3. Secrets: move client secrets, bind passwords and data source passwords out of annotations and files into runtime configuration or a vault.
  4. Hashing: raise the iteration count and rehash on successful login; measure login latency under load first.
  5. Federation: move user-facing apps to the OpenID Connect mechanism so MFA and lifecycle sit at the identity provider; keep a local break-glass admin.
  6. Logging: add mechanism wrappers and role-change audit events, then build the detections above.

Testing and rollback: run integration tests that send every HTTP method to each protected URL and expect 401 or 403. Ship constraint and mechanism changes behind a deployment you can roll back as a whole. The hash format records the iteration count per hash, so raising iterations does not lock out existing users and can be reverted.

Small versus large teams: a single application can use the database or LDAP store directly. Organisations with many applications should standardise on OpenID Connect to a central provider and keep local stores only for break-glass access.

Common misconfigurations

  • Method lists in security constraints: constraining GET and POST only, so DELETE or PUT on the same URL is unauthenticated.
  • Default PBKDF2 iterations: 2,048 iterations makes offline cracking of a stolen user table far cheaper than OWASP's guidance assumes. See the Password Hashing and Key Derivation Guide.
  • Literal secrets in annotations: client secrets and bind passwords committed to Git and visible in compiled classes (T1552.001 Credentials In Files).
  • In-memory store left in production: demo users with known passwords shipped in a release build.
  • Role checks only at the URL layer: beans and REST resources reachable through other paths without @RolesAllowed.
  • Basic authentication on internet-facing endpoints: no lockout or MFA, an easy target for credential stuffing.

Framework mapping

Control areaNIST SP 800-53 Rev. 5NIST CSF 2.0OWASP ASVS 5.0ISO/IEC 27001:2022 Annex A
Authentication mechanisms and federationIA-2, IA-5PR.AA-03V6 AuthenticationA.8.5
Password storageIA-5(1)PR.AA-01V11.4.2A.5.17
Roles and constraintsAC-3, AC-6PR.AA-05V8 AuthorizationA.8.3
Transport and sessionsSC-8, SC-23PR.DS-02V7 Session ManagementA.8.24
Audit eventsAU-2, AU-12DE.CM-09V16 Security Logging and Error HandlingA.8.15

Practitioner checklist

  • Code authentication against Jakarta Security APIs, not server-specific realm classes.
  • Set Pbkdf2PasswordHash.Iterations to at least 600,000 for PBKDF2WithHmacSHA256 and rehash on login.
  • Resolve clientSecret, bindDnPassword and data source passwords from runtime configuration or a vault.
  • Add <deny-uncovered-http-methods/> and CONFIDENTIAL transport guarantees to every web module.
  • Put @DenyAll on sensitive beans and grant methods with @RolesAllowed.
  • Remove in-memory identity stores from production builds.
  • Use LDAPS, a read-only bind account and a non-zero LDAP read timeout.
  • Prefer the OpenID Connect mechanism with nonce and an exact redirect URI for user logins.
  • Log authentication results and role changes without credentials, and alert on spraying patterns.

Standards and references

Related NHI Mgmt Group resources: Java and Spring Security Guide · JBoss EAP and WildFly Hardening · OAuth 2.0 and OpenID Connect Guide · Password Hashing and Key Derivation Guide · OWASP ASVS Guide

Free weekly newsletter

Subscribe to the NHI & AI Identity Journal

The latest on NHI and Agentic AI security – articles, research, breaches, news and events every week.

Bonus 33% off our NHI Course when you subscribe.

NHIMG Editorial Note
Researched and written by the NHI Mgmt Group editorial team using AI tools, under the editorial direction of Lalit Choda. Facts are drawn from the sources listed on this page and checked by our automated quality process. Last updated 8 November 2026. Spotted an error? Use our contact page.
NHI Mgmt Group, the independent authority on Non-Human Identity, IAM and Agentic AI security. nhimg.org