CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-eclipse-jetty--jetty-security

Security framework for Eclipse Jetty providing authentication, authorization, and user identity management.

Pending
Overview
Eval results
Files

jaas.mddocs/

JAAS Integration

Java Authentication and Authorization Service (JAAS) integration provides enterprise-grade authentication with pluggable login modules and standardized security contexts.

Core JAAS Components

JAASLoginService

Main login service for JAAS integration:

public class JAASLoginService extends AbstractLoginService {
    
    // Default role class name
    public static final String DEFAULT_ROLE_CLASS_NAME = "org.eclipse.jetty.security.jaas.JAASRole";
    
    // Thread-local instance access
    public static final ThreadLocal<JAASLoginService> INSTANCE = new ThreadLocal<>();
    
    // Constructors
    public JAASLoginService();
    public JAASLoginService(String name);
    
    // Configuration
    public String getName();
    public void setName(String name);
    
    public Configuration getConfiguration();
    public void setConfiguration(Configuration configuration);
    
    // Login module configuration
    public void setLoginModuleName(String name);
    public String getLoginModuleName();
    
    // Callback handler configuration  
    public void setCallbackHandlerClass(String classname);
    public String getCallbackHandlerClass();
    
    // Role class configuration
    public void setRoleClassNames(String[] classnames);
    public String[] getRoleClassNames();
    
    @Override
    protected UserPrincipal loadUserInfo(String username);
    
    @Override
    protected List<RolePrincipal> loadRoleInfo(UserPrincipal user);
}

JAASUserPrincipal

Principal for JAAS-authenticated users:

public class JAASUserPrincipal extends UserPrincipal {
    
    // Constructor
    public JAASUserPrincipal(String name, Subject subject, LoginContext loginContext);
    
    // JAAS-specific access
    public LoginContext getLoginContext();
    public Subject getSubject();
    
    @Override
    public void configureSubject(Subject subject);
    
    @Override
    public void deconfigureSubject(Subject subject);
}

JAAS Principals and Roles

JAASRole

Principal representing a role in JAAS authentication:

public class JAASRole extends JAASPrincipal {
    
    public JAASRole(String roleName);
    
    @Override
    public String getName();
    
    @Override
    public boolean equals(Object other);
    
    @Override
    public int hashCode();
}

JAASPrincipal

Base class for JAAS principals:

public abstract class JAASPrincipal implements Principal, Serializable {
    
    protected JAASPrincipal(String name);
    
    @Override
    public abstract String getName();
    
    @Override
    public boolean equals(Object other);
    
    @Override
    public int hashCode();
    
    @Override
    public String toString();
}

JAAS Callback Handlers

AbstractCallbackHandler

Base class for JAAS callback handlers:

public abstract class AbstractCallbackHandler implements CallbackHandler {
    
    // Protected fields for subclasses
    protected String _userName;
    protected Object _credential;
    protected Request _request;
    
    // Accessor methods
    public void setUserName(String userName);
    public void setCredential(Object credential);
    public void setRequest(Request request);
    
    @Override
    public abstract void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException;
}

DefaultCallbackHandler

Default implementation supporting common callback types:

public class DefaultCallbackHandler extends AbstractCallbackHandler {
    
    // Configuration
    public void setRequest(Request request);
    public void setCredential(Object credential);
    public void setUserName(String userName);
    
    @Override
    public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
        
        for (Callback callback : callbacks) {
            
            if (callback instanceof NameCallback) {
                NameCallback nameCallback = (NameCallback) callback;
                nameCallback.setName(_userName);
                
            } else if (callback instanceof PasswordCallback) {
                PasswordCallback passwordCallback = (PasswordCallback) callback;
                if (_credential instanceof String) {
                    passwordCallback.setPassword(((String) _credential).toCharArray());
                }
                
            } else if (callback instanceof ObjectCallback) {
                ObjectCallback objectCallback = (ObjectCallback) callback;
                objectCallback.setObject(_credential);
                
            } else if (callback instanceof RequestCallback) {
                RequestCallback requestCallback = (RequestCallback) callback;
                requestCallback.setRequest(_request);
                
            } else if (callback instanceof RequestParameterCallback) {
                RequestParameterCallback paramCallback = (RequestParameterCallback) callback;
                paramCallback.setParameterValues(_request.getParameters().getValues(paramCallback.getParameterName()));
                
            } else {
                throw new UnsupportedCallbackException(callback);
            }
        }
    }
}

Custom Callback Types

// ObjectCallback - for retrieving arbitrary objects
public class ObjectCallback implements Callback {
    
    public ObjectCallback();
    
    public void setObject(Object obj);
    public Object getObject();
    
    public void clearObject();
}

// RequestCallback - for retrieving the current HTTP request
public class RequestCallback implements Callback {
    
    public RequestCallback();
    
    public void setRequest(Request request);
    public Request getRequest();
}

// RequestParameterCallback - for retrieving request parameters
public class RequestParameterCallback implements Callback {
    
    public RequestParameterCallback(String parameterName);
    
    public String getParameterName();
    public void setParameterValues(List<String> parameterValues);
    public List<String> getParameterValues();
}

JAAS Login Modules

AbstractLoginModule

Base class for JAAS login modules:

public abstract class AbstractLoginModule implements LoginModule {
    
    // JAAS lifecycle
    @Override
    public boolean initialize(Subject subject, CallbackHandler callbackHandler, 
                             Map<String, ?> sharedState, Map<String, ?> options);
    
    @Override
    public boolean login() throws LoginException;
    
    @Override
    public boolean commit() throws LoginException;
    
    @Override
    public boolean abort() throws LoginException;
    
    @Override
    public boolean logout() throws LoginException;
    
    // Protected utility methods for subclasses
    protected Set<JAASRole> getRoles() throws IOException, UnsupportedCallbackException;
    protected UserPrincipal getUserPrincipal(String username) throws IOException, UnsupportedCallbackException;
}

AbstractDatabaseLoginModule

Base for database-backed login modules:

public abstract class AbstractDatabaseLoginModule extends AbstractLoginModule {
    
    // Database connection management
    protected String dbDriver;
    protected String dbUrl; 
    protected String dbUserName;
    protected String dbPassword;
    
    // Connection lifecycle
    protected Connection getConnection() throws SQLException;
    protected void closeConnection(Connection connection);
    
    // Abstract methods for subclasses
    protected abstract UserInfo getUserInfo(String username) throws SQLException;
    protected abstract List<String> getUserRoles(String username) throws SQLException;
}

JDBCLoginModule

JAAS login module for JDBC database authentication:

public class JDBCLoginModule extends AbstractDatabaseLoginModule {
    
    // Configuration options (set in JAAS config file)
    // - dbDriver: JDBC driver class name
    // - dbUrl: Database URL
    // - dbUserName: Database username
    // - dbPassword: Database password
    // - userTable: User table name
    // - userField: Username column name
    // - credentialField: Password column name
    // - roleTable: Role table name
    // - roleField: Role name column name
    // - userRoleTable: User-role mapping table name
    
    @Override
    public boolean login() throws LoginException {
        
        try {
            // Get credentials from callback handler
            Callback[] callbacks = new Callback[] {
                new NameCallback("Username: "),
                new PasswordCallback("Password: ", false)
            };
            
            callbackHandler.handle(callbacks);
            
            String username = ((NameCallback) callbacks[0]).getName();
            char[] password = ((PasswordCallback) callbacks[1]).getPassword();
            
            // Authenticate against database
            if (authenticateUser(username, password)) {
                // Load user and roles
                currentUser = loadUserPrincipal(username);
                currentRoles = loadUserRoles(username);
                return true;
            }
            
            return false;
            
        } catch (Exception e) {
            throw new LoginException("JDBC authentication failed: " + e.getMessage());
        }
    }
    
    @Override
    protected UserInfo getUserInfo(String username) throws SQLException;
    
    @Override  
    protected List<String> getUserRoles(String username) throws SQLException;
    
    private boolean authenticateUser(String username, char[] password) throws SQLException;
    private UserPrincipal loadUserPrincipal(String username) throws SQLException;
    private Set<JAASRole> loadUserRoles(String username) throws SQLException;
}

DataSourceLoginModule

JAAS login module using DataSource:

public class DataSourceLoginModule extends AbstractDatabaseLoginModule {
    
    // Configuration options:
    // - dataSourceName: JNDI name of DataSource
    // - userTable, userField, credentialField: User table configuration
    // - roleTable, roleField, userRoleTable: Role table configuration
    
    @Override
    protected Connection getConnection() throws SQLException {
        // Use JNDI DataSource instead of direct connection
        InitialContext ctx = new InitialContext();
        DataSource ds = (DataSource) ctx.lookup(dataSourceName);
        return ds.getConnection();
    }
    
    @Override
    protected UserInfo getUserInfo(String username) throws SQLException;
    
    @Override
    protected List<String> getUserRoles(String username) throws SQLException;
}

LdapLoginModule

JAAS login module for LDAP authentication:

public class LdapLoginModule extends AbstractLoginModule {
    
    // LDAP configuration options:
    // - hostname: LDAP server hostname
    // - port: LDAP server port
    // - contextFactory: LDAP context factory class
    // - bindDn: Bind DN for LDAP connection
    // - bindPassword: Bind password
    // - userBaseDn: Base DN for user searches
    // - roleBaseDn: Base DN for role searches  
    // - userIdAttribute: User ID attribute name
    // - userPasswordAttribute: Password attribute name
    // - userObjectClass: User object class
    // - roleIdAttribute: Role ID attribute name
    // - roleMemberAttribute: Role membership attribute
    // - roleObjectClass: Role object class
    
    @Override
    public boolean login() throws LoginException {
        
        try {
            // Get credentials from callback handler
            Callback[] callbacks = new Callback[] {
                new NameCallback("Username: "),
                new PasswordCallback("Password: ", false)
            };
            
            callbackHandler.handle(callbacks);
            
            String username = ((NameCallback) callbacks[0]).getName();
            char[] password = ((PasswordCallback) callbacks[1]).getPassword();
            
            // Authenticate against LDAP
            if (authenticateWithLDAP(username, password)) {
                currentUser = createUserPrincipal(username);
                currentRoles = loadLDAPRoles(username);
                return true;
            }
            
            return false;
            
        } catch (Exception e) {
            throw new LoginException("LDAP authentication failed: " + e.getMessage());
        }
    }
    
    private boolean authenticateWithLDAP(String username, char[] password) throws Exception;
    private UserPrincipal createUserPrincipal(String username) throws Exception;
    private Set<JAASRole> loadLDAPRoles(String username) throws Exception;
}

PropertyFileLoginModule

JAAS login module for property file authentication:

public class PropertyFileLoginModule extends AbstractLoginModule {
    
    // Configuration options:
    // - file: Path to properties file
    
    @Override
    public boolean login() throws LoginException {
        
        try {
            // Get credentials from callback handler
            Callback[] callbacks = new Callback[] {
                new NameCallback("Username: "),
                new PasswordCallback("Password: ", false)
            };
            
            callbackHandler.handle(callbacks);
            
            String username = ((NameCallback) callbacks[0]).getName();
            char[] password = ((PasswordCallback) callbacks[1]).getPassword();
            
            // Load properties file
            Properties users = loadUserProperties();
            
            // Authenticate user
            String userEntry = users.getProperty(username);
            if (userEntry != null && authenticateUser(userEntry, password)) {
                currentUser = createUserPrincipal(username);
                currentRoles = parseRoles(userEntry);
                return true;
            }
            
            return false;
            
        } catch (Exception e) {
            throw new LoginException("Property file authentication failed: " + e.getMessage());
        }
    }
    
    private Properties loadUserProperties() throws IOException;
    private boolean authenticateUser(String userEntry, char[] password);
    private UserPrincipal createUserPrincipal(String username);
    private Set<JAASRole> parseRoles(String userEntry);
}

JAAS Configuration

Programmatic Configuration

public class JAASConfigurationExample {
    
    public void setupJAASLoginService() {
        JAASLoginService jaasLogin = new JAASLoginService();
        jaasLogin.setName("JAASRealm");
        
        // Set login module name (must match JAAS config)
        jaasLogin.setLoginModuleName("myLoginModule");
        
        // Set callback handler
        jaasLogin.setCallbackHandlerClass("com.example.MyCallbackHandler");
        
        // Configure role classes
        jaasLogin.setRoleClassNames(new String[] {
            "org.eclipse.jetty.security.jaas.JAASRole",
            "com.example.CustomRole"
        });
        
        // Use with security handler
        SecurityHandler security = new SecurityHandler.PathMapped();
        security.setLoginService(jaasLogin);
    }
    
    public void setupProgrammaticConfiguration() {
        
        // Create JAAS configuration programmatically
        Configuration jaasConfig = new Configuration() {
            @Override
            public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
                
                if ("myLoginModule".equals(name)) {
                    Map<String, String> options = new HashMap<>();
                    options.put("dbDriver", "com.mysql.cj.jdbc.Driver");
                    options.put("dbUrl", "jdbc:mysql://localhost:3306/users");
                    options.put("dbUserName", "app");
                    options.put("dbPassword", "secret");
                    options.put("userTable", "users");
                    options.put("userField", "username");
                    options.put("credentialField", "password");
                    options.put("roleTable", "roles");
                    options.put("roleField", "role_name");
                    options.put("userRoleTable", "user_roles");
                    
                    AppConfigurationEntry entry = new AppConfigurationEntry(
                        "org.eclipse.jetty.security.jaas.spi.JDBCLoginModule",
                        AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
                        options
                    );
                    
                    return new AppConfigurationEntry[] { entry };
                }
                
                return null;
            }
        };
        
        // Set the configuration
        JAASLoginService jaasLogin = new JAASLoginService();
        jaasLogin.setConfiguration(jaasConfig);
    }
}

JAAS Configuration Files

// jaas.conf file format

// JDBC Login Module Configuration
myApp-JDBC {
    org.eclipse.jetty.security.jaas.spi.JDBCLoginModule required
    dbDriver="com.mysql.cj.jdbc.Driver"
    dbUrl="jdbc:mysql://localhost:3306/myapp"
    dbUserName="app_user"
    dbPassword="app_password"
    userTable="users"
    userField="username"  
    credentialField="password"
    roleTable="user_roles"
    roleField="role"
    userRoleTable="user_roles";
};

// LDAP Login Module Configuration
myApp-LDAP {
    org.eclipse.jetty.security.jaas.spi.LdapLoginModule required
    hostname="ldap.example.com"
    port="389"
    contextFactory="com.sun.jndi.ldap.LdapCtxFactory"
    bindDn="cn=admin,dc=example,dc=com"
    bindPassword="secret"
    userBaseDn="ou=users,dc=example,dc=com"
    roleBaseDn="ou=roles,dc=example,dc=com"
    userIdAttribute="uid"
    userPasswordAttribute="userPassword"
    userObjectClass="inetOrgPerson"
    roleIdAttribute="cn"
    roleMemberAttribute="member"
    roleObjectClass="groupOfNames";
};

// Property File Login Module Configuration  
myApp-Properties {
    org.eclipse.jetty.security.jaas.spi.PropertyFileLoginModule required
    file="/etc/myapp/users.properties";
};

// Multi-module configuration (try LDAP first, fallback to local)
myApp-Multi {
    org.eclipse.jetty.security.jaas.spi.LdapLoginModule sufficient
    hostname="ldap.example.com"
    port="389"
    userBaseDn="ou=users,dc=example,dc=com";
    
    org.eclipse.jetty.security.jaas.spi.PropertyFileLoginModule required
    file="/etc/myapp/local-users.properties";
};

System Property Configuration

public class JAASSystemConfiguration {
    
    public void configureJAASSystemProperties() {
        
        // Set JAAS configuration file
        System.setProperty("java.security.auth.login.config", "/path/to/jaas.conf");
        
        // Enable JAAS debug logging
        System.setProperty("java.security.debug", "logincontext,policy,scl,gssloginconfig");
        
        // Set security manager (if required)
        System.setProperty("java.security.manager", "");
        System.setProperty("java.security.policy", "/path/to/security.policy");
        
        // Kerberos configuration (for SPNEGO)
        System.setProperty("java.security.krb5.conf", "/etc/krb5.conf");
        System.setProperty("sun.security.krb5.debug", "true");
        
        // Create JAAS login service
        JAASLoginService jaasLogin = new JAASLoginService("MyRealm");
        jaasLogin.setLoginModuleName("myApp-JDBC");
    }
}

PropertyUserStoreManager

Managing Property User Stores

public class PropertyUserStoreManager {
    
    // Static store management
    public static PropertyUserStore getPropertyUserStore(String name);
    public static PropertyUserStore getPropertyUserStore(String name, String configPath);
    
    // Store lifecycle
    public static void addPropertyUserStore(String name, PropertyUserStore store);
    public static void removePropertyUserStore(String name);
    
    // Configuration management
    public static void setReloadInterval(String name, int seconds);
    public static void enableHotReload(String name, boolean enable);
}

Advanced JAAS Examples

Custom Login Module

public class TokenLoginModule extends AbstractLoginModule {
    
    @Override
    public boolean initialize(Subject subject, CallbackHandler callbackHandler, 
                             Map<String, ?> sharedState, Map<String, ?> options) {
        
        super.initialize(subject, callbackHandler, sharedState, options);
        
        // Get configuration options
        this.tokenValidator = (String) options.get("tokenValidator");
        this.roleAttribute = (String) options.get("roleAttribute");
        
        return true;
    }
    
    @Override
    public boolean login() throws LoginException {
        
        try {
            // Custom callback for token
            Callback[] callbacks = new Callback[] {
                new ObjectCallback() // Custom token callback
            };
            
            callbackHandler.handle(callbacks);
            
            Object token = ((ObjectCallback) callbacks[0]).getObject();
            
            if (validateToken(token)) {
                TokenInfo tokenInfo = parseToken(token);
                currentUser = createUserPrincipal(tokenInfo.getSubject());
                currentRoles = createRoles(tokenInfo.getRoles());
                return true;
            }
            
            return false;
            
        } catch (Exception e) {
            throw new LoginException("Token authentication failed: " + e.getMessage());
        }
    }
    
    private boolean validateToken(Object token);
    private TokenInfo parseToken(Object token);
    private UserPrincipal createUserPrincipal(String subject);
    private Set<JAASRole> createRoles(List<String> roleNames);
    
    private static class TokenInfo {
        public String getSubject() { return null; }
        public List<String> getRoles() { return Collections.emptyList(); }
    }
}

Multi-Realm JAAS Configuration

public class MultiRealmJAAS {
    
    public void setupMultipleRealms() {
        
        // Primary realm with LDAP
        JAASLoginService primaryRealm = new JAASLoginService();
        primaryRealm.setName("PrimaryRealm");
        primaryRealm.setLoginModuleName("primary-ldap");
        primaryRealm.setCallbackHandlerClass("com.example.LDAPCallbackHandler");
        
        // Admin realm with local properties
        JAASLoginService adminRealm = new JAASLoginService();
        adminRealm.setName("AdminRealm");
        adminRealm.setLoginModuleName("admin-properties");
        adminRealm.setCallbackHandlerClass("com.example.PropertiesCallbackHandler");
        
        // API realm with token authentication
        JAASLoginService apiRealm = new JAASLoginService();
        apiRealm.setName("APIRealm");
        apiRealm.setLoginModuleName("api-tokens");
        apiRealm.setCallbackHandlerClass("com.example.TokenCallbackHandler");
        
        // Configure different security handlers for different areas
        SecurityHandler.PathMapped webSecurity = new SecurityHandler.PathMapped();
        webSecurity.setLoginService(primaryRealm);
        webSecurity.put("/app/*", Constraint.ANY_USER);
        
        SecurityHandler.PathMapped adminSecurity = new SecurityHandler.PathMapped();
        adminSecurity.setLoginService(adminRealm);
        adminSecurity.put("/admin/*", Constraint.from("admin"));
        
        SecurityHandler.PathMapped apiSecurity = new SecurityHandler.PathMapped();
        apiSecurity.setLoginService(apiRealm);
        apiSecurity.put("/api/*", Constraint.from("api-user"));
    }
}

JAAS with Custom Callback Handler

public class CustomJAASCallbackHandler extends AbstractCallbackHandler {
    
    @Override
    public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
        
        for (Callback callback : callbacks) {
            
            if (callback instanceof NameCallback) {
                handleNameCallback((NameCallback) callback);
                
            } else if (callback instanceof PasswordCallback) {
                handlePasswordCallback((PasswordCallback) callback);
                
            } else if (callback instanceof ObjectCallback) {
                handleObjectCallback((ObjectCallback) callback);
                
            } else if (callback instanceof RequestCallback) {
                handleRequestCallback((RequestCallback) callback);
                
            } else if (callback instanceof RequestParameterCallback) {
                handleRequestParameterCallback((RequestParameterCallback) callback);
                
            } else if (callback instanceof ChoiceCallback) {
                handleChoiceCallback((ChoiceCallback) callback);
                
            } else {
                throw new UnsupportedCallbackException(callback, 
                    "Callback type not supported: " + callback.getClass().getName());
            }
        }
    }
    
    private void handleNameCallback(NameCallback callback) {
        // Extract username from request headers, parameters, or attributes
        String username = extractUsernameFromRequest();
        callback.setName(username);
    }
    
    private void handlePasswordCallback(PasswordCallback callback) {
        // Extract password from request or use token-based authentication
        String password = extractPasswordFromRequest();
        callback.setPassword(password != null ? password.toCharArray() : null);
    }
    
    private void handleObjectCallback(ObjectCallback callback) {
        // Handle custom object callbacks (e.g., tokens, certificates)
        Object credential = extractCustomCredential();
        callback.setObject(credential);
    }
    
    private void handleRequestCallback(RequestCallback callback) {
        // Provide the HTTP request to login modules
        callback.setRequest(_request);
    }
    
    private void handleRequestParameterCallback(RequestParameterCallback callback) {
        // Extract specific request parameters
        String paramName = callback.getParameterName();
        List<String> values = _request.getParameters().getValues(paramName);
        callback.setParameterValues(values);
    }
    
    private void handleChoiceCallback(ChoiceCallback callback) {
        // Handle multiple choice selections (e.g., authentication methods)
        String[] choices = callback.getChoices();
        int selectedIndex = determineChoice(choices);
        callback.setSelectedIndex(selectedIndex);
    }
    
    private String extractUsernameFromRequest() {
        // Implementation to extract username
        return null;
    }
    
    private String extractPasswordFromRequest() {
        // Implementation to extract password
        return null;
    }
    
    private Object extractCustomCredential() {
        // Implementation to extract custom credentials
        return null;
    }
    
    private int determineChoice(String[] choices) {
        // Implementation to determine choice
        return 0;
    }
}

Security Best Practices

JAAS Security Configuration

public class JAASSecurityBestPractices {
    
    public void configureSecureJAAS() {
        
        JAASLoginService jaasLogin = new JAASLoginService();
        jaasLogin.setName("SecureRealm");
        
        // Use strong authentication methods
        jaasLogin.setLoginModuleName("multi-factor-ldap");
        
        // Custom callback handler with security validations
        jaasLogin.setCallbackHandlerClass("com.example.SecureCallbackHandler");
        
        // Configure multiple role classes for fine-grained access control
        jaasLogin.setRoleClassNames(new String[] {
            "org.eclipse.jetty.security.jaas.JAASRole",
            "com.example.ApplicationRole",
            "com.example.PermissionRole"
        });
        
        // Enable comprehensive logging
        System.setProperty("java.security.debug", "access,logincontext,policy");
        
        // Set up security manager
        setupSecurityManager();
    }
    
    private void setupSecurityManager() {
        // Configure security policy for JAAS
        System.setProperty("java.security.policy", "/etc/myapp/security.policy");
        
        // Enable security manager
        if (System.getSecurityManager() == null) {
            System.setSecurityManager(new SecurityManager());
        }
    }
}

JAAS integration provides enterprise-grade authentication with standardized login modules, flexible callback handling, and comprehensive security contexts for complex authentication scenarios.

Install with Tessl CLI

npx tessl i tessl/maven-org-eclipse-jetty--jetty-security

docs

authentication.md

index.md

jaas.md

login-services.md

security-framework.md

user-identity.md

tile.json