Return to site

🔐🧩 SECURING JAVA EE APPLICATIONS: IDENTITY STORES + AUTH MECHANISMS

· jakartaee

🔸 TLDR

▪️ Java EE (Jakarta Security) lets you secure apps by combining Identity Stores (where users/roles come from) + Authentication Mechanisms (how users prove who they are).

▪️ Start simple (DB + BASIC/FORM), then evolve (LDAP, custom stores, custom auth flows) without rewriting your whole app. ✅

Section image

🔸 THE TWO BUILDING BLOCKS (MENTAL MODEL) 🧠

▪️ Identity Store = “Where are my users, passwords, and roles?” (DB, LDAP, custom…)

▪️ Auth Mechanism = “How does the user authenticate?” (BASIC, FORM, custom…)

▪️ Jakarta Security wires them together so your app code stays clean.

🔸 IDENTITY STORES: DATABASE (RELATIONAL) 🗄️

Typical setup: one table for users + one for roles (or a join table).

import jakarta.security.enterprise.identitystore.DatabaseIdentityStoreDefinition;
import jakarta.security.enterprise.identitystore.PasswordHash;

@DatabaseIdentityStoreDefinition(
  dataSourceLookup = "java:app/jdbc/securityDS",
  callerQuery = "SELECT password FROM app_user WHERE username = ?",
  groupsQuery = "SELECT role FROM app_user_role WHERE username = ?",
  hashAlgorithm = PasswordHash.class
)
public class SecurityConfig {}

▪️ Your container executes the queries, verifies the password hash, and loads roles into the security context.

▪️ Bonus: this scales well for classic enterprise apps with existing schemas.

🔸 IDENTITY STORES: LDAP DIRECTORY 📇

Great when identities are centralized (company directory, SSO ecosystem, org-wide roles).

import jakarta.security.enterprise.identitystore.LdapIdentityStoreDefinition;

@LdapIdentityStoreDefinition(
  url = "ldap://ldap.company.local:389",
  callerBaseDn = "ou=people,dc=company,dc=local",
  groupBaseDn  = "ou=groups,dc=company,dc=local",
  callerNameAttribute = "uid",
  groupSearchFilter = "(&(member={0})(objectClass=groupOfNames))"
)
public class SecurityConfig {}

▪️ LDAP becomes your source of truth for users + group membership.

▪️ Ideal for internal apps: less password management in your app.

🔸 IDENTITY STORES: CUSTOM (WHEN REAL LIFE GETS MESSY) 🧰

When you need API calls, multi-tenant rules, legacy systems, or non-standard credential checks.

import jakarta.security.enterprise.credential.UsernamePasswordCredential;
import jakarta.security.enterprise.identitystore.CredentialValidationResult;
import jakarta.security.enterprise.identitystore.IdentityStore;

import java.util.Set;

public class CustomIdentityStore implements IdentityStore {

  @Override
  public CredentialValidationResult validate(UsernamePasswordCredential cred) {
    // 1) load user from anywhere (API, DB, cache…)
    // 2) verify password/hash
    // 3) return roles
    boolean ok = check(cred.getCaller(), cred.getPasswordAsString());

    return ok
      ? new CredentialValidationResult(cred.getCaller(), Set.of("USER", "ADMIN"))
      : CredentialValidationResult.INVALID_RESULT;
  }

  private boolean check(String username, String rawPassword) {
    // your custom verification
    return true;
  }
}

▪️ Keep it small: validate credentials + return roles.

▪️ Put the heavy logic behind a service (so you can test it).

🔸 AUTHENTICATION MECHANISMS: BASIC (FASTEST TO START) ⚡

Perfect for APIs, internal tools, and quick prototypes.

import jakarta.security.enterprise.authentication.mechanism.http.BasicAuthenticationMechanismDefinition;

@BasicAuthenticationMechanismDefinition(
  realmName = "my-realm"
)
public class SecurityConfig {}

▪️ Works great over HTTPS.

▪️ Browser UX is basic (pun intended 😄), but API clients love it.

🔸 AUTHENTICATION MECHANISMS: FORM (CLASSIC WEB APPS) 🧑💻

For server-rendered apps where you want a login page.

import jakarta.security.enterprise.authentication.mechanism.http.FormAuthenticationMechanismDefinition;

@FormAuthenticationMechanismDefinition(
  loginToContinue = @jakarta.security.enterprise.authentication.mechanism.http.LoginToContinue(
    loginPage = "/login.xhtml",
    errorPage = "/login-error.xhtml"
  )
)
public class SecurityConfig {}

▪️ You control the pages.

▪️ The container handles redirects + security context creation.

🔸 CUSTOM FORM AUTH (FULL CONTROL OVER THE FLOW) 🛠️

Use this when you want extra steps: CAPTCHA, MFA prompts, tenant selection, “magic link”, etc.

import jakarta.security.enterprise.authentication.mechanism.http.HttpAuthenticationMechanism;
import jakarta.security.enterprise.authentication.mechanism.http.AuthenticationParameters;
import jakarta.security.enterprise.SecurityContext;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;

@ApplicationScoped
public class CustomFormAuth implements HttpAuthenticationMechanism {

  @Inject SecurityContext securityContext;

  @Override
  public jakarta.security.enterprise.AuthenticationStatus validateRequest(
      HttpServletRequest request,
      HttpServletResponse response,
      jakarta.security.enterprise.authentication.mechanism.http.HttpMessageContext context) {

    if ("/login".equals(request.getServletPath()) && "POST".equalsIgnoreCase(request.getMethod())) {
      String user = request.getParameter("username");
      String pass = request.getParameter("password");

      return context.notifyContainerAboutLogin(
        securityContext.authenticate(request, response,
          AuthenticationParameters.withParams().credential(new jakarta.security.enterprise.credential.UsernamePasswordCredential(user, pass)))
      );
    }
    return context.doNothing();
  }
}

▪️ You decide when/how to trigger authentication.

▪️ Still reuse Identity Stores for validation + role loading.

🔸 TAKEAWAYS ✅

▪️ Identity Store answers “who are you + what roles do you have?”

▪️ Auth Mechanism answers “how do you prove it?”

▪️ Start with DB + BASIC/FORM, then move to LDAP for centralized identities.

▪️ Use custom store for legacy/complex rules, and custom mechanism for advanced UX/security flows.

▪️ Keep security testable: push logic into services, keep the mechanism/store thin.

#Java #JavaEE #JakartaEE #JakartaSecurity #Security #Authentication #Authorization #LDAP #EnterpriseJava #SoftwareEngineering

Go further with Java certification:

Java👇

Spring👇

SpringBook👇

JavaBook👇