google-site-verification: google61fe8ba583a51912.html
JAAS Authentication and Authorization in Java

Overview

Java Authentication and Authorization Service (JAAS) is a Java security framework that provides a pluggable and extensible architecture for authenticating users and enforcing access controls. It separates the concerns of authentication from authorization and allows for flexible security implementations.

Core Concepts

  • Subject: Represents the current user or service
  • Principal: Identity attribute (username, role, group)
  • Credential: Proof of identity (password, certificate)
  • LoginContext: Entry point for authentication
  • LoginModule: Pluggable authentication modules
  • CallbackHandler: Handles user interaction during login

Basic Setup and Dependencies

Maven Dependencies

<dependencies> <!-- Core JAAS (part of Java SE) --> <dependency> <groupId>javax.security.auth</groupId> <artifactId>jaas</artifactId> <version>1.0.1</version> <scope>system</scope> <systemPath>${java.home}/lib/jaas.jar</systemPath> </dependency> <!-- For custom LoginModules --> <dependency> <groupId>javax.security</groupId> <artifactId>jacc</artifactId> <version>1.0</version> </dependency> </dependencies>

Basic JAAS Authentication

Example 1: Simple File-Based Authentication

import javax.security.auth.*; import javax.security.auth.login.*; import javax.security.auth.callback.*; import java.io.*; import java.util.*; public class BasicJAASAuthentication { public static void main(String[] args) { try { // Create LoginContext with configuration name and callback handler LoginContext loginContext = new LoginContext("SimpleFileLogin", new SimpleCallbackHandler()); // Perform authentication loginContext.login(); System.out.println("Authentication successful!"); // Get the authenticated subject Subject subject = loginContext.getSubject(); System.out.println("Subject: " + subject); System.out.println("Principals: " + subject.getPrincipals()); // Perform secured action performSecuredAction(subject); // Logout loginContext.logout(); System.out.println("Logout successful!"); } catch (LoginException e) { System.err.println("Authentication failed: " + e.getMessage()); } } private static void performSecuredAction(Subject subject) { // Execute action with subject's permissions Subject.doAs(subject, new PrivilegedAction<Void>() { @Override public Void run() { System.out.println("Performing secured action as: " + Subject.getSubject(AccessController.getContext())); // Perform some secured operation here return null; } }); } } // Custom CallbackHandler for handling user interaction class SimpleCallbackHandler implements CallbackHandler { @Override public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for (Callback callback : callbacks) { if (callback instanceof NameCallback) { NameCallback nameCallback = (NameCallback) callback; System.out.print(nameCallback.getPrompt()); nameCallback.setName(new Scanner(System.in).nextLine()); } else if (callback instanceof PasswordCallback) { PasswordCallback passwordCallback = (PasswordCallback) callback; System.out.print(passwordCallback.getPrompt()); passwordCallback.setPassword(new Scanner(System.in).nextLine().toCharArray()); } else { throw new UnsupportedCallbackException(callback, "Unsupported callback type"); } } } }

JAAS Configuration File (jaas.config)

SimpleFileLogin { com.example.SimpleFileLoginModule required debug=true; }; DatabaseLogin { com.example.DatabaseLoginModule sufficient dbUrl="jdbc:mysql://localhost:3306/authdb" dbUser="auth_user" dbPassword="auth_pass"; }; LDAPLogin { com.example.LDAPLoginModule sufficient ldapUrl="ldap://localhost:389" baseDN="dc=example,dc=com"; }; CompositeLogin { com.example.LDAPLoginModule sufficient ldapUrl="ldap://localhost:389" baseDN="dc=example,dc=com"; com.example.DatabaseLoginModule sufficient dbUrl="jdbc:mysql://localhost:3306/authdb"; com.example.SimpleFileLoginModule required; };

Custom LoginModule Implementation

Example 2: File-Based LoginModule

import javax.security.auth.*; import javax.security.auth.spi.*; import javax.security.auth.callback.*; import javax.security.auth.login.*; import java.io.*; import java.util.*; import java.security.Principal; public class SimpleFileLoginModule implements LoginModule { private Subject subject; private CallbackHandler callbackHandler; private Map<String, ?> sharedState; private Map<String, ?> options; private String username; private Set<Principal> principals; private boolean authenticated = false; private boolean committed = false; // Configuration options private String userFile; private boolean debug; @Override public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState, Map<String, ?> options) { this.subject = subject; this.callbackHandler = callbackHandler; this.sharedState = sharedState; this.options = options; // Read configuration options this.userFile = (String) options.get("userFile"); this.debug = "true".equals(options.get("debug")); if (this.userFile == null) { this.userFile = "users.properties"; } if (debug) { System.out.println("SimpleFileLoginModule initialized"); } } @Override public boolean login() throws LoginException { if (callbackHandler == null) { throw new LoginException("No CallbackHandler available"); } try { // Create callbacks for username and password NameCallback nameCallback = new NameCallback("Username: "); PasswordCallback passwordCallback = new PasswordCallback("Password: ", false); Callback[] callbacks = new Callback[]{nameCallback, passwordCallback}; callbackHandler.handle(callbacks); username = nameCallback.getName(); char[] password = passwordCallback.getPassword(); if (username == null || password == null) { throw new LoginException("Username or password cannot be null"); } // Authenticate against user file authenticated = authenticateUser(username, new String(password)); if (authenticated) { principals = new HashSet<>(); principals.add(new UsernamePrincipal(username)); principals.add(new RolePrincipal("USER")); // Default role if (debug) { System.out.println("Authentication successful for user: " + username); } return true; } else { throw new FailedLoginException("Invalid username or password"); } } catch (IOException | UnsupportedCallbackException e) { LoginException le = new LoginException("Authentication process failed"); le.initCause(e); throw le; } } private boolean authenticateUser(String username, String password) { Properties users = new Properties(); try (InputStream input = new FileInputStream(userFile)) { users.load(input); String storedPassword = users.getProperty(username); return storedPassword != null && storedPassword.equals(password); } catch (IOException e) { System.err.println("Error reading user file: " + e.getMessage()); return false; } } @Override public boolean commit() throws LoginException { if (!authenticated) { return false; } // Add principals to subject subject.getPrincipals().addAll(principals); committed = true; if (debug) { System.out.println("Login committed for user: " + username); } return true; } @Override public boolean abort() throws LoginException { if (!authenticated) { return false; } if (!committed) { authenticated = false; username = null; principals = null; } else { logout(); } if (debug) { System.out.println("Login aborted for user: " + username); } return true; } @Override public boolean logout() throws LoginException { subject.getPrincipals().removeAll(principals); authenticated = false; committed = false; username = null; principals = null; if (debug) { System.out.println("User logged out"); } return true; } } // Custom Principal implementations class UsernamePrincipal implements Principal { private final String name; public UsernamePrincipal(String name) { this.name = name; } @Override public String getName() { return name; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null || getClass() != obj.getClass()) return false; UsernamePrincipal that = (UsernamePrincipal) obj; return Objects.equals(name, that.name); } @Override public int hashCode() { return Objects.hash(name); } @Override public String toString() { return "UsernamePrincipal: " + name; } } class RolePrincipal implements Principal { private final String role; public RolePrincipal(String role) { this.role = role; } @Override public String getName() { return role; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null || getClass() != obj.getClass()) return false; RolePrincipal that = (RolePrincipal) obj; return Objects.equals(role, that.role); } @Override public int hashCode() { return Objects.hash(role); } @Override public String toString() { return "RolePrincipal: " + role; } }

Example 3: Database LoginModule

import javax.security.auth.*; import javax.security.auth.spi.*; import javax.security.auth.callback.*; import javax.security.auth.login.*; import java.sql.*; import java.util.*; import java.security.Principal; public class DatabaseLoginModule implements LoginModule { private Subject subject; private CallbackHandler callbackHandler; private Map<String, ?> options; private String username; private Set<Principal> principals; private boolean authenticated = false; private boolean committed = false; // Database configuration private String dbUrl; private String dbUser; private String dbPassword; private boolean debug; @Override public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState, Map<String, ?> options) { this.subject = subject; this.callbackHandler = callbackHandler; this.options = options; this.dbUrl = (String) options.get("dbUrl"); this.dbUser = (String) options.get("dbUser"); this.dbPassword = (String) options.get("dbPassword"); this.debug = "true".equals(options.get("debug")); if (dbUrl == null) { throw new IllegalArgumentException("Database URL is required"); } } @Override public boolean login() throws LoginException { if (callbackHandler == null) { throw new LoginException("No CallbackHandler available"); } try { NameCallback nameCallback = new NameCallback("Username: "); PasswordCallback passwordCallback = new PasswordCallback("Password: ", false); Callback[] callbacks = new Callback[]{nameCallback, passwordCallback}; callbackHandler.handle(callbacks); username = nameCallback.getName(); char[] password = passwordCallback.getPassword(); if (username == null || password == null) { throw new LoginException("Username or password cannot be null"); } // Authenticate against database authenticated = authenticateAgainstDatabase(username, new String(password)); if (authenticated) { principals = new HashSet<>(); principals.add(new UsernamePrincipal(username)); // Get user roles from database Set<String> roles = getUserRoles(username); for (String role : roles) { principals.add(new RolePrincipal(role)); } if (debug) { System.out.println("Database authentication successful for user: " + username); System.out.println("Roles: " + roles); } return true; } else { throw new FailedLoginException("Invalid database credentials"); } } catch (Exception e) { LoginException le = new LoginException("Database authentication failed"); le.initCause(e); throw le; } } private boolean authenticateAgainstDatabase(String username, String password) { String sql = "SELECT password FROM users WHERE username = ? AND active = true"; try (Connection conn = DriverManager.getConnection(dbUrl, dbUser, dbPassword); PreparedStatement stmt = conn.prepareStatement(sql)) { stmt.setString(1, username); ResultSet rs = stmt.executeQuery(); if (rs.next()) { String storedPassword = rs.getString("password"); return storedPassword != null && storedPassword.equals(hashPassword(password)); } } catch (SQLException e) { System.err.println("Database error: " + e.getMessage()); } return false; } private Set<String> getUserRoles(String username) { Set<String> roles = new HashSet<>(); String sql = "SELECT r.role_name FROM user_roles ur " + "JOIN roles r ON ur.role_id = r.id " + "JOIN users u ON ur.user_id = u.id " + "WHERE u.username = ?"; try (Connection conn = DriverManager.getConnection(dbUrl, dbUser, dbPassword); PreparedStatement stmt = conn.prepareStatement(sql)) { stmt.setString(1, username); ResultSet rs = stmt.executeQuery(); while (rs.next()) { roles.add(rs.getString("role_name")); } } catch (SQLException e) { System.err.println("Error fetching user roles: " + e.getMessage()); } return roles; } private String hashPassword(String password) { // Simple hash for demonstration - use proper hashing in production return Integer.toHexString(password.hashCode()); } @Override public boolean commit() throws LoginException { if (!authenticated) { return false; } subject.getPrincipals().addAll(principals); committed = true; return true; } @Override public boolean abort() throws LoginException { if (!authenticated) { return false; } if (!committed) { authenticated = false; username = null; principals = null; } else { logout(); } return true; } @Override public boolean logout() throws LoginException { subject.getPrincipals().removeAll(principals); authenticated = false; committed = false; username = null; principals = null; return true; } }

Authorization with JAAS

Example 4: Role-Based Authorization

import javax.security.auth.Subject; import java.security.Principal; import java.security.PrivilegedAction; import java.util.Set; public class JAASAuthorizationExample { public static void main(String[] args) { try { // Authenticate user LoginContext loginContext = new LoginContext("DatabaseLogin", new ConsoleCallbackHandler()); loginContext.login(); Subject subject = loginContext.getSubject(); System.out.println("Authenticated subject: " + subject); // Check authorization if (hasRole(subject, "ADMIN")) { performAdminAction(subject); } else if (hasRole(subject, "USER")) { performUserAction(subject); } else { System.out.println("Insufficient privileges"); } // Logout loginContext.logout(); } catch (LoginException e) { System.err.println("Authentication failed: " + e.getMessage()); } } public static boolean hasRole(Subject subject, String role) { Set<RolePrincipal> roles = subject.getPrincipals(RolePrincipal.class); return roles.stream().anyMatch(principal -> principal.getName().equals(role)); } public static void performAdminAction(final Subject subject) { Subject.doAsPrivileged(subject, new PrivilegedAction<Void>() { @Override public Void run() { // Check permission at runtime SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(new AdminPermission()); } System.out.println("Performing ADMIN action"); // Admin-specific logic here return null; } }, null); } public static void performUserAction(final Subject subject) { Subject.doAs(subject, new PrivilegedAction<Void>() { @Override public Void run() { SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(new UserPermission()); } System.out.println("Performing USER action"); // User-specific logic here return null; } }); } } // Custom Permissions class AdminPermission extends java.security.BasicPermission { public AdminPermission() { super("admin"); } public AdminPermission(String name, String actions) { super(name, actions); } } class UserPermission extends java.security.BasicPermission { public UserPermission() { super("user"); } } // Console-based CallbackHandler class ConsoleCallbackHandler implements CallbackHandler { @Override public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { Scanner scanner = new Scanner(System.in); for (Callback callback : callbacks) { if (callback instanceof NameCallback) { NameCallback nameCallback = (NameCallback) callback; System.out.print(nameCallback.getPrompt()); nameCallback.setName(scanner.nextLine()); } else if (callback instanceof PasswordCallback) { PasswordCallback passwordCallback = (PasswordCallback) callback; System.out.print(passwordCallback.getPrompt()); passwordCallback.setPassword(scanner.nextLine().toCharArray()); } else { throw new UnsupportedCallbackException(callback, "Unsupported callback"); } } } }

Example 5: Policy-Based Authorization

import java.io.File; import java.io.FilePermission; import java.security.Policy; import java.security.Principal; import java.security.ProtectionDomain; import java.security.CodeSource; import java.security.Permission; import java.security.PermissionCollection; import java.security.AllPermission; import java.util.*; public class JAASPolicy extends Policy { private final Map<String, Set<Permission>> rolePermissions; public JAASPolicy() { rolePermissions = new HashMap<>(); initializeRolePermissions(); } private void initializeRolePermissions() { // Define permissions for each role Set<Permission> adminPermissions = new HashSet<>(); adminPermissions.add(new AllPermission()); adminPermissions.add(new FilePermission("<<ALL FILES>>", "read,write,execute,delete")); rolePermissions.put("ADMIN", adminPermissions); Set<Permission> userPermissions = new HashSet<>(); userPermissions.add(new FilePermission("/home/user/-", "read,write")); userPermissions.add(new RuntimePermission("accessDeclaredMembers")); userPermissions.put("USER", userPermissions); Set<Permission> guestPermissions = new HashSet<>(); guestPermissions.add(new FilePermission("/home/user/public/-", "read")); rolePermissions.put("GUEST", guestPermissions); } @Override public PermissionCollection getPermissions(ProtectionDomain domain) { Permissions permissions = new Permissions(); // Add default permissions addDefaultPermissions(permissions); // Add role-based permissions Principal[] principals = domain.getPrincipals(); if (principals != null) { for (Principal principal : principals) { if (principal instanceof RolePrincipal) { String role = principal.getName(); Set<Permission> rolePerms = rolePermissions.get(role); if (rolePerms != null) { for (Permission perm : rolePerms) { permissions.add(perm); } } } } } return permissions; } @Override public PermissionCollection getPermissions(CodeSource codesource) { return new Permissions(); // Empty permissions } @Override public boolean implies(ProtectionDomain domain, Permission permission) { return getPermissions(domain).implies(permission); } private void addDefaultPermissions(Permissions permissions) { // Add basic permissions for all authenticated users permissions.add(new RuntimePermission("accessDeclaredMembers")); permissions.add(new PropertyPermission("user.*", "read")); permissions.add(new FilePermission("/tmp/-", "read,write")); } } // Policy setup class PolicySetup { static { // Set custom policy Policy.setPolicy(new JAASPolicy()); System.setSecurityManager(new SecurityManager()); } public static void setup() { // Static initializer does the setup } }

Advanced JAAS Features

Example 6: Multi-Module Authentication Stack

public class MultiModuleAuthentication { public static void main(String[] args) { try { // Configuration with multiple LoginModules LoginContext loginContext = new LoginContext( "CompositeLogin", new InteractiveCallbackHandler() ); loginContext.login(); Subject subject = loginContext.getSubject(); System.out.println("Authentication successful!"); System.out.println("Subject principals:"); subject.getPrincipals().forEach(System.out::println); // Execute with subject's permissions Subject.doAs(subject, (PrivilegedAction<Void>) () -> { System.out.println("Executing with subject's permissions"); // Perform authorized actions return null; }); loginContext.logout(); } catch (LoginException e) { System.err.println("Authentication failed: " + e.getMessage()); } } } class InteractiveCallbackHandler implements CallbackHandler { private Scanner scanner = new Scanner(System.in); @Override public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for (Callback callback : callbacks) { if (callback instanceof NameCallback) { NameCallback nameCallback = (NameCallback) callback; System.out.print(nameCallback.getPrompt()); String name = scanner.nextLine(); nameCallback.setName(name); } else if (callback instanceof PasswordCallback) { PasswordCallback passwordCallback = (PasswordCallback) callback; System.out.print(passwordCallback.getPrompt()); String password = scanner.nextLine(); passwordCallback.setPassword(password.toCharArray()); } else if (callback instanceof TextOutputCallback) { TextOutputCallback textCallback = (TextOutputCallback) callback; switch (textCallback.getMessageType()) { case TextOutputCallback.INFORMATION: System.out.println("INFO: " + textCallback.getMessage()); break; case TextOutputCallback.WARNING: System.out.println("WARNING: " + textCallback.getMessage()); break; case TextOutputCallback.ERROR: System.out.println("ERROR: " + textCallback.getMessage()); break; } } else if (callback instanceof ChoiceCallback) { ChoiceCallback choiceCallback = (ChoiceCallback) callback; System.out.println(choiceCallback.getPrompt()); String[] options = choiceCallback.getOptions(); for (int i = 0; i < options.length; i++) { System.out.println((i + 1) + ". " + options[i]); } System.out.print("Enter choice: "); int choice = scanner.nextInt(); scanner.nextLine(); // consume newline choiceCallback.setSelectedIndex(choice - 1); } else { throw new UnsupportedCallbackException(callback, "Unsupported callback type"); } } } }

Example 7: JAAS in Web Applications

// Web application authentication filter public class JAASAuthFilter implements Filter { private static final String LOGIN_CONFIG = "WebAppLogin"; @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest = (HttpServletRequest) request; HttpServletResponse httpResponse = (HttpServletResponse) response; HttpSession session = httpRequest.getSession(); try { // Check if user is already authenticated Subject subject = (Subject) session.getAttribute("javax.security.auth.subject"); if (subject == null) { // Attempt authentication subject = authenticateUser(httpRequest); if (subject != null) { session.setAttribute("javax.security.auth.subject", subject); } else { httpResponse.sendRedirect("/login.jsp"); return; } } // Continue with authenticated user chain.doFilter(request, response); } catch (LoginException e) { httpResponse.sendRedirect("/login.jsp?error=auth_failed"); } } private Subject authenticateUser(HttpServletRequest request) throws LoginException { String username = request.getParameter("username"); String password = request.getParameter("password"); if (username == null || password == null) { return null; } CallbackHandler callbackHandler = new HttpRequestCallbackHandler(username, password); LoginContext loginContext = new LoginContext(LOGIN_CONFIG, callbackHandler); loginContext.login(); return loginContext.getSubject(); } @Override public void init(FilterConfig filterConfig) throws ServletException { // Initialization code } @Override public void destroy() { // Cleanup code } } // CallbackHandler for HTTP requests class HttpRequestCallbackHandler implements CallbackHandler { private final String username; private final String password; public HttpRequestCallbackHandler(String username, String password) { this.username = username; this.password = password; } @Override public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for (Callback callback : callbacks) { if (callback instanceof NameCallback) { ((NameCallback) callback).setName(username); } else if (callback instanceof PasswordCallback) { ((PasswordCallback) callback).setPassword(password.toCharArray()); } else { throw new UnsupportedCallbackException(callback, "Unsupported callback type"); } } } } // Role-based web authorization public class RoleAuthorizationFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest = (HttpServletRequest) request; HttpServletResponse httpResponse = (HttpServletResponse) response; HttpSession session = httpRequest.getSession(); Subject subject = (Subject) session.getAttribute("javax.security.auth.subject"); if (subject == null || !hasRequiredRole(subject, httpRequest)) { httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN, "Insufficient privileges"); return; } chain.doFilter(request, response); } private boolean hasRequiredRole(Subject subject, HttpServletRequest request) { String requiredRole = getRequiredRole(request); if (requiredRole == null) { return true; // No specific role required } return subject.getPrincipals(RolePrincipal.class).stream() .anyMatch(principal -> principal.getName().equals(requiredRole)); } private String getRequiredRole(HttpServletRequest request) { // Extract required role from request URL or configuration String path = request.getServletPath(); if (path.startsWith("/admin/")) { return "ADMIN"; } else if (path.startsWith("/user/")) { return "USER"; } else if (path.startsWith("/api/")) { return "API_USER"; } return null; } @Override public void init(FilterConfig filterConfig) throws ServletException {} @Override public void destroy() {} }

JAAS Configuration Management

Example 8: Dynamic Configuration

import javax.security.auth.login.Configuration; import java.security.Security; import java.util.*; public class DynamicJAASConfiguration extends Configuration { private final Map<String, AppConfigurationEntry[]> configurations; public DynamicJAASConfiguration() { this.configurations = new HashMap<>(); } public void addConfiguration(String name, AppConfigurationEntry[] entries) { configurations.put(name, entries); } public void removeConfiguration(String name) { configurations.remove(name); } @Override public AppConfigurationEntry[] getAppConfigurationEntry(String name) { return configurations.get(name); } // Method to create configuration from properties public static DynamicJAASConfiguration fromProperties(Properties props) { DynamicJAASConfiguration config = new DynamicJAASConfiguration(); // Parse properties and create configurations Set<String> configNames = new HashSet<>(); for (String key : props.stringPropertyNames()) { if (key.contains(".")) { configNames.add(key.substring(0, key.indexOf('.'))); } } for (String configName : configNames) { AppConfigurationEntry[] entries = parseConfigurationEntries(props, configName); config.addConfiguration(configName, entries); } return config; } private static AppConfigurationEntry[] parseConfigurationEntries(Properties props, String configName) { List<AppConfigurationEntry> entries = new ArrayList<>(); int index = 0; while (true) { String entryKey = configName + "." + index; String moduleClass = props.getProperty(entryKey + ".module"); if (moduleClass == null) { break; } String flag = props.getProperty(entryKey + ".flag", "required"); Map<String, String> options = new HashMap<>(); // Parse options for (String propName : props.stringPropertyNames()) { if (propName.startsWith(entryKey + ".option.")) { String optionName = propName.substring(entryKey.length() + 8); // ".option." length options.put(optionName, props.getProperty(propName)); } } AppConfigurationEntry.LoginModuleControlControlFlag controlFlag; switch (flag.toLowerCase()) { case "required": controlFlag = AppConfigurationEntry.LoginModuleControlControlFlag.REQUIRED; break; case "requisite": controlFlag = AppConfigurationEntry.LoginModuleControlControlFlag.REQUISITE; break; case "sufficient": controlFlag = AppConfigurationEntry.LoginModuleControlControlFlag.SUFFICIENT; break; case "optional": controlFlag = AppConfigurationEntry.LoginModuleControlControlFlag.OPTIONAL; break; default: controlFlag = AppConfigurationEntry.LoginModuleControlControlFlag.REQUIRED; } entries.add(new AppConfigurationEntry( moduleClass, controlFlag, options )); index++; } return entries.toArray(new AppConfigurationEntry[0]); } } // Usage example public class DynamicConfigurationExample { public static void main(String[] args) { Properties props = new Properties(); props.setProperty("WebLogin.0.module", "com.example.DatabaseLoginModule"); props.setProperty("WebLogin.0.flag", "required"); props.setProperty("WebLogin.0.option.dbUrl", "jdbc:mysql://localhost/auth"); props.setProperty("WebLogin.0.option.debug", "true"); props.setProperty("WebLogin.1.module", "com.example.LDAPLoginModule"); props.setProperty("WebLogin.1.flag", "sufficient"); props.setProperty("WebLogin.1.option.ldapUrl", "ldap://localhost"); DynamicJAASConfiguration config = DynamicJAASConfiguration.fromProperties(props); Configuration.setConfiguration(config); // Now use the configuration try { LoginContext ctx = new LoginContext("WebLogin", new SimpleCallbackHandler()); ctx.login(); // ... rest of authentication logic } catch (LoginException e) { e.printStackTrace(); } } }

Best Practices and Security Considerations

  1. Use strong password hashing in LoginModules
  2. Implement proper error handling to avoid information leakage
  3. Use secure communication for remote authentication
  4. Regularly update and patch custom LoginModules
  5. Implement proper session management in web applications
  6. Use principle of least privilege in authorization policies
  7. Audit and log authentication attempts
  8. Secure configuration files and sensitive data
  9. Use HTTPS for web-based authentication
  10. Implement account lockout mechanisms for brute force protection

JAAS provides a robust framework for implementing authentication and authorization in Java applications. By following these patterns and best practices, you can build secure, flexible, and maintainable security solutions.

Leave a Reply

Your email address will not be published. Required fields are marked *


Macro Nepal Helper