Chapter 3. Legacy Security Subsystem 3.1. Configure a Security Domain to use LDAP Security domains can be configured to use an LDAP server for authentication and authorization by using a login module. The basics of security domains and login modules are covered in the JBoss EAP Security Architecture guide . LdapExtended is the preferred login module for integrating with LDAP servers (including Active Directory), but there are several other LDAP login modules that can be used as well. Specifically, the Ldap , AdvancedLdap , and AdvancedAdLdap login modules can also be used to configure a security domain to use LDAP. This section uses the LdapExtended login module to illustrate how to create a security domain that uses LDAP for authentication and authorization, but the other LDAP login modules can be used as well. For more details on the other LDAP login modules, see the JBoss EAP Login Module Reference . Important In cases where the legacy security subsystem uses an LDAP server to perform authentication, JBoss EAP will return a 500 , or internal server error, error code if that LDAP server is unreachable. This behavior differs from versions of JBoss EAP which returned a 401 , or unauthorized, error code under the same conditions. 3.1.1. LdapExtended Login Module LdapExtended ( org.jboss.security.auth.spi.LdapExtLoginModule ) is a login module implementation that uses searches to locate the bind user and associated roles on an LDAP server. The roles query recursively follows DNs to navigate a hierarchical role structure. For the vast majority of cases when using LDAP with security domains, the LdapExtended login module should be used, especially with LDAP implementations that are not Active Directory. For a full list of configuration options for the LdapExtended login module, see the LdapExtended login module section in the JBoss EAP Login Module Reference . The authentication happens as follows: An initial bind to the LDAP server is done using the bindDN and bindCredential options. The bindDN is a LDAP user with the ability to search both the baseCtxDN and rolesCtxDN trees for the user and roles. The user DN to authenticate against is queried using the filter specified by the baseFilter attribute. The resulting user DN is authenticated by binding to the LDAP server using the user DN as the InitialLdapContext environment Context.SECURITY_PRINCIPAL . The Context.SECURITY_CREDENTIALS property is set to the String password obtained by the callback handler. 3.1.1.1. Configure a Security Domain to use the LdapExtended Login Module Example Data (LDIF format) CLI Commands for Adding the LdapExtended Login Module /subsystem=security/security-domain=testLdapExtendedExample:add(cache-type=default) /subsystem=security/security-domain=testLdapExtendedExample/authentication=classic:add /subsystem=security/security-domain=testLdapExtendedExample/authentication=classic/login-module=LdapExtended:add(code=LdapExtended, flag=required, module-options=[ ("java.naming.factory.initial"=>"com.sun.jndi.ldap.LdapCtxFactory"), ("java.naming.provider.url"=>"ldap://localhost:10389"), ("java.naming.security.authentication"=>"simple"), ("bindDN"=>"uid=ldap,ou=Users,dc=jboss,dc=org"), ("bindCredential"=>"randall"), ("baseCtxDN"=>"ou=Users,dc=jboss,dc=org"), ("baseFilter"=>"(uid={0})"), ("rolesCtxDN"=>"ou=groups,dc=jboss,dc=org"), ("roleFilter"=>"(uniqueMember={1})"), ("roleAttributeID"=>"uid")]) reload Note The management CLI commands shown assume that you are running a JBoss EAP standalone server. For more details on using the management CLI for a JBoss EAP managed domain, see the JBoss EAP Management CLI Guide . 3.1.1.1.1. Configure a Security Domain to use the LdapExtended Login Module for Active Directory For Microsoft Active Directory, the LdapExtended login module can be used. The example below represents the configuration for a default Active Directory configuration. Some Active Directory configurations may require searching against the Global Catalog on port 3268 instead of the usual port 389 . This is most likely when the Active Directory forest includes multiple domains. Example Configuration for the LdapExtended Login Module for a Default AD Configuration The example below implements a recursive role search within Active Directory. The key difference between this example and the default Active Directory example is that the role search has been replaced to search the member attribute using the DN of the user. The login module then uses the DN of the role to find groups of which the group is a member. Example Configuration for the LdapExtended Login Module for a Default AD Configuration with Recursive Search 3.2. Configure a Security Domain to use a Database Similar to LDAP, security domains can be configured to use a database for authentication and authorization by using a login module. 3.2.1. Database Login Module The Database login module is a JDBC login module that supports authentication and role mapping. This login module is used if username, password, and role information are stored in a relational database. This works by providing a reference to logical tables containing principals and roles in the expected format. For example: Table Principals(PrincipalID text, Password text) Table Roles(PrincipalID text, Role text, RoleGroup text) The Principals table associates the user PrincipalID with the valid password, and the Roles table associates the user PrincipalID with its role sets. The roles used for user permissions must be contained in rows with a RoleGroup column value of Roles . The tables are logical in that users can specify the SQL query that the login module uses. The only requirement is that the java.sql.ResultSet has the same logical structure as the Principals and Roles tables described previously. The actual names of the tables and columns are not relevant as the results are accessed based on the column index. To clarify this concept, consider a database with two tables, Principals and Roles , as already declared. The following statements populate the tables with the following data: PrincipalID java with a password of echoman in the Principals table PrincipalID java with a role named Echo in the RolesRoleGroup in the Roles table PrincipalID java with a role named caller-java in the CallerPrincipalRoleGroup in the Roles table For a full list of configuration options for the Database login module, see the Database login module section in the JBoss EAP Login Module Reference . 3.2.1.1. Configure a Security Domain to use the Database Login Module Before configuring a security domain to use the Database login module, a datasource must be properly configured. For more information on creating and configuring datasources in JBoss EAP, see the Datasource Management section of the JBoss EAP Configuration Guide . Once a datasource has been properly configured, a security domain can be configured to use the Database login module. The below example assumes a datasource named MyDatabaseDS has been created and properly configured with a database that is constructed with the following: CREATE TABLE Users(username VARCHAR(64) PRIMARY KEY, passwd VARCHAR(64)) CREATE TABLE UserRoles(username VARCHAR(64), role VARCHAR(32)) CLI Commands for Adding the Database Login Module /subsystem=security/security-domain=testDB:add /subsystem=security/security-domain=testDB/authentication=classic:add /subsystem=security/security-domain=testDB/authentication=classic/login-module=Database:add(code=Database,flag=required,module-options=[("dsJndiName"=>"java:/MyDatabaseDS"),("principalsQuery"=>"select passwd from Users where username=?"),("rolesQuery"=>"select role, 'Roles' from UserRoles where username=?")]) reload 3.3. Configure a Security Domain to use a Properties File Security domains can also be configured to use a filesystem as an identity store for authentication and authorization by using a login module. 3.3.1. UsersRoles Login Module UsersRoles is a simple login module that supports multiple users and user roles loaded from Java properties files. The primary purpose of this login module is to easily test the security settings of multiple users and roles using properties files deployed with the application. The default username-to-password mapping filename is users.properties and the default username-to-roles mapping filename is roles.properties . Note This login module supports password stacking, password hashing, and unauthenticated identity. The properties files are loaded during initialization using the initialize method thread context class loader. This means that these files can be placed on the classpath of the Jakarta EE deployment (for example, into the WEB-INF/classes folder in the WAR archive), or into any directory on the server classpath. For a full list of configuration options for the UsersRoles login module, see the UsersRoles login module section in the JBoss EAP Login Module Reference . 3.3.1.1. Configure a Security Domain to use the UsersRoles Login Module The below example assumes the following files have been created and are available on the application's classpath: sampleapp-users.properties sampleapp-roles.properties CLI Commands for Adding the UserRoles Login Module /subsystem=security/security-domain=sampleapp:add /subsystem=security/security-domain=sampleapp/authentication=classic:add /subsystem=security/security-domain=sampleapp/authentication=classic/login-module=UsersRoles:add(code=UsersRoles,flag=required,module-options=[("usersProperties"=>"sampleapp-users.properties"),("rolesProperties"=>"sampleapp-roles.properties")]) reload 3.4. Configure a Security Domain to use Certificate-Based Authentication JBoss EAP provides you with the ability to use certificate-based authentication with security domains to secure web applications or Jakarta Enterprise Beans. Important Before you can configure certificate-based authentication, you need to have Two-Way SSL/TLS for Applications enabled and configured, which requires X509 certificates configured for both the JBoss EAP instance as well as any clients accessing the web application or Jakarta Enterprise Beans secured by the security domain. Once the certificates, truststores, and two-way SSL/TLS are configured, you then can proceed with configuring a security domain that uses certificate-based authentication, configuring an application to use that security domain, and configuring your client to use the client certificate. 3.4.1. Creating a Security Domain with Certificate-Based Authentication To create a security domain that uses certificate-based authentication, you need to specify a truststore as well as a Certificate login module or one of its subclasses. The truststore must contain any trusted client certificates used for authentication, or it must contain the certificate of the certificate authority used to sign the client's certificate. The login module is used to authenticate the certificate presented by the client using the configured truststore. The security domain as a whole also must provide a way to map a role to the principal once it is authenticated. The Certificate login module itself will not map any role information to the principal, but it may be combined with another login module to do so. Alternatively, two subclasses of the Certificate login module, CertificateRoles and DatabaseCertificate , do provide a way to map roles to a principal after it is authenticated. The below example shows how to configure a security domain with certificate-based authentication using the CertificateRoles login module. Warning When performing authentication, the security domain will use the same certificate presented by the client when establishing two-way SSL/TLS. As a result, the client must use the same certificate for BOTH two-way SSL/TLS and the certificate-based authentication with the application or Jakarta Enterprise Beans. Example Security Domain with Certificate-Based Authentication Note The above example uses the CertificateRoles login module to handle authentication and map roles to authenticated principals. It does so by referencing a properties file using the rolesProperties attribute. This file lists usernames and roles using the following format: Since usernames are presented as the DN from the provided certificate, for example CN=valid-client, OU=JBoss, O=Red Hat, L=Raleigh, ST=NC, C=US , you have to escape special characters such as = and spaces when using a properties file: Example Roles Properties File To view, the DN of certificate: 3.4.2. Configure an Application to use a Security Domain with Certificate-Based Authentication Similar to configuring an application to use a security domain with other forms of authentication, you need to configure both the jboss-web.xml and web.xml files appropriately. For jboss-web.xml , add a reference to the security domain you configured for certificate-based authentication. Example jboss-web.xml <jboss-web> <security-domain>cert-roles-domain</security-domain> </jboss-web> For web.xml , set the <auth-method> attribute in <login-config> to CLIENT-CERT . You also need define <security-constraint> as well as <security-roles> . Example web.xml <web-app> <!-- URL for secured portion of application--> <security-constraint> <web-resource-collection> <web-resource-name>secure</web-resource-name> <url-pattern>/secure/*</url-pattern> </web-resource-collection> <auth-constraint> <role-name>All</role-name> </auth-constraint> </security-constraint> <!-- Security roles referenced by this web application --> <security-role> <description>The role that is required to log in to the application</description> <role-name>All</role-name> </security-role> <login-config> <auth-method>CLIENT-CERT</auth-method> <realm-name>cert-roles-domain</realm-name> </login-config> </web-app> 3.4.3. Configure the Client For a client to authenticate against an application secured with certificate-based authentication, the client needs access to a client certificate that is contained in the JBoss EAP instance's truststore. For example, if accessing the application using a browser, the client will need to import the trusted certificate into the browser's truststore. 3.5. Configure Caching for a Security Domain You can specify a cache for a security domain to speed up authentication checks. By default, a security domain uses a simple map as the cache. This default cache is a Least Recently Used (LRU) cache with a maximum of 1000 entries. Alternatively, you can set a security domain to use an Infinispan cache, or disable caching altogether. 3.5.1. Setting the Cache Type for a Security Domain Prerequisites If you are configuring a security domain to use an Infinispan cache, you must first create an Infinispan cache container named security that contains a default cache that the security domain will use. Important You can only define one Infinispan cache configuration for use with security domains. Although you can have multiple security domains that use an Infinispan cache, each security domain creates its own cache instance from the one Infinispan cache configuration. See the JBoss EAP Configuration Guide for more information on creating a cache container . You can use either the management console or management CLI to set a security domain's cache type. To use the management console: Navigate to Configuration Subsystems Security (Legacy) . Select the security domain from the list and click View . Click Edit , and for the Cache Type field, select either default or infinspan . Click Save . To use the management CLI, use the following command: For example, to set the other security domain to use an Infinispan cache: 3.5.2. Listing and Flushing Principals Listing Principals in the Cache You can see the principals that are stored in a security domain's cache using the following management CLI command: Flushing Principals from the Cache If required, you can flush principals from a security domain's cache. To flush a specific principal, use the following management CLI command: To flush all principals from the cache, use the following management CLI command: 3.5.3. Disabling Caching for a Security Domain You can use either the management console or management CLI to disable caching for a security domain. To use the management console: Navigate to Configuration Subsystems Security (Legacy) . Select the security domain from the list and click View . Click Edit and select the blank value for the Cache Type . Click Save . To use the management CLI, use the following command:

Commands:
dn: uid=jduke,ou=Users,dc=jboss,dc=org objectClass: inetOrgPerson objectClass: person objectClass: top cn: Java Duke sn: duke uid: jduke userPassword: theduke ============================= dn: uid=hnelson,ou=Users,dc=jboss,dc=org objectClass: inetOrgPerson objectClass: person objectClass: top cn: Horatio Nelson sn: Nelson uid: hnelson userPassword: secret ============================= dn: ou=groups,dc=jboss,dc=org objectClass: top objectClass: organizationalUnit ou: groups ============================= dn: uid=ldap,ou=Users,dc=jboss,dc=org objectClass: inetOrgPerson objectClass: person objectClass: top cn: LDAP sn: Service uid: ldap userPassword: randall ============================= dn: ou=Users,dc=jboss,dc=org objectClass: top objectClass: organizationalUnit ou: Users ============================= dn: dc=jboss,dc=org objectclass: top objectclass: domain dc: jboss ============================= dn: uid=GroupTwo,ou=groups,dc=jboss,dc=org objectClass: top objectClass: groupOfNames objectClass: uidObject cn: GroupTwo member: uid=jduke,ou=Users,dc=jboss,dc=org uid: GroupTwo ============================= dn: uid=GroupThree,ou=groups,dc=jboss,dc=org objectClass: top objectClass: groupOfUniqueNames objectClass: uidObject cn: GroupThree uid: GroupThree uniqueMember: uid=GroupOne,ou=groups,dc=jboss,dc=org ============================= dn: uid=HTTP,ou=Users,dc=jboss,dc=org objectClass: inetOrgPerson objectClass: person objectClass: top cn: HTTP sn: Service uid: HTTP userPassword: httppwd ============================= dn: uid=GroupOne,ou=groups,dc=jboss,dc=org objectClass: top objectClass: groupOfUniqueNames objectClass: uidObject cn: GroupOne uid: GroupOne uniqueMember: uid=jduke,ou=Users,dc=jboss,dc=org uniqueMember: uid=hnelson,ou=Users,dc=jboss,dc=org
/subsystem=security/security-domain=testLdapExtendedExample:add(cache-type=default) /subsystem=security/security-domain=testLdapExtendedExample/authentication=classic:add /subsystem=security/security-domain=testLdapExtendedExample/authentication=classic/login-module=LdapExtended:add(code=LdapExtended, flag=required, module-options=[ ("java.naming.factory.initial"=>"com.sun.jndi.ldap.LdapCtxFactory"), ("java.naming.provider.url"=>"ldap://localhost:10389"), ("java.naming.security.authentication"=>"simple"), ("bindDN"=>"uid=ldap,ou=Users,dc=jboss,dc=org"), ("bindCredential"=>"randall"), ("baseCtxDN"=>"ou=Users,dc=jboss,dc=org"), ("baseFilter"=>"(uid={0})"), ("rolesCtxDN"=>"ou=groups,dc=jboss,dc=org"), ("roleFilter"=>"(uniqueMember={1})"), ("roleAttributeID"=>"uid")]) reload
/subsystem=security/security-domain=AD_Default:add(cache-type=default) /subsystem=security/security-domain=AD_Default/authentication=classic:add /subsystem=security/security-domain=AD_Default/authentication=classic/login-module=LdapExtended:add(code=LdapExtended,flag=required,module-options=[ ("java.naming.provider.url"=>"ldap://ldaphost.jboss.org"),("bindDN"=>"JBOSSsearchuser"), ("bindCredential"=>"password"), ("baseCtxDN"=>"CN=Users,DC=jboss,DC=org"), ("baseFilter"=>"(sAMAccountName={0})"), ("rolesCtxDN"=>"CN=Users,DC=jboss,DC=org"), ("roleFilter"=>"(sAMAccountName={0})"), ("roleAttributeID"=>"memberOf"), ("roleAttributeIsDN"=>"true"), ("roleNameAttributeID"=>"cn"), ("searchScope"=>"ONELEVEL_SCOPE"), ("allowEmptyPasswords"=>"false")]) reload
/subsystem=security/security-domain=AD_Recursive:add(cache-type=default) /subsystem=security/security-domain=AD_Recursive/authentication=classic:add /subsystem=security/security-domain=AD_Recursive/authentication=classic/login-module=LdapExtended:add(code=LdapExtended,flag=required,module-options=[("java.naming.provider.url"=>"ldap://ldaphost.jboss.org"), ("java.naming.referral"=>"follow"), ("bindDN"=>"JBOSSsearchuser"), ("bindCredential"=>"password"), ("baseCtxDN"=>"CN=Users,DC=jboss,DC=org"), ("baseFilter"=>"(sAMAccountName={0})"), ("rolesCtxDN"=>"CN=Users,DC=jboss,DC=org"), ("roleFilter"=>"(member={1})"), ("roleAttributeID"=>"cn"), ("roleAttributeIsDN"=>"false"), ("roleRecursion"=>"2"), ("searchScope"=>"ONELEVEL_SCOPE"), ("allowEmptyPasswords"=>"false")]) reload
Table Principals(PrincipalID text, Password text) Table Roles(PrincipalID text, Role text, RoleGroup text)
CREATE TABLE Users(username VARCHAR(64) PRIMARY KEY, passwd VARCHAR(64)) CREATE TABLE UserRoles(username VARCHAR(64), role VARCHAR(32))
/subsystem=security/security-domain=testDB:add /subsystem=security/security-domain=testDB/authentication=classic:add /subsystem=security/security-domain=testDB/authentication=classic/login-module=Database:add(code=Database,flag=required,module-options=[("dsJndiName"=>"java:/MyDatabaseDS"),("principalsQuery"=>"select passwd from Users where username=?"),("rolesQuery"=>"select role, 'Roles' from UserRoles where username=?")]) reload
/subsystem=security/security-domain=sampleapp:add /subsystem=security/security-domain=sampleapp/authentication=classic:add /subsystem=security/security-domain=sampleapp/authentication=classic/login-module=UsersRoles:add(code=UsersRoles,flag=required,module-options=[("usersProperties"=>"sampleapp-users.properties"),("rolesProperties"=>"sampleapp-roles.properties")]) reload
/subsystem=security/security-domain=cert-roles-domain:add /subsystem=security/security-domain=cert-roles-domain/jsse=classic:add(truststore={password=secret, url="/path/to/server.truststore.jks"}, keystore={password=secret, url="/path/to/server.keystore.jks"}, client-auth=true) /subsystem=security/security-domain=cert-roles-domain/authentication=classic:add /subsystem=security/security-domain=cert-roles-domain/authentication=classic/login-module=CertificateRoles:add(code=CertificateRoles, flag=required, module-options=[ securityDomain="cert-roles-domain", rolesProperties="USD{jboss.server.config.dir}/cert-roles.properties",password-stacking="useFirstPass", verifier="org.jboss.security.auth.certs.AnyCertVerifier"])
user1=roleA user2=roleB,roleC user3=
CN\=valid-client,\ OU\=JBoss,\ O\=Red\ Hat,\ L\=Raleigh,\ ST\=NC,\ C\=US=Admin
keytool -printcert -file valid-client.crt Owner: CN=valid-client, OU=JBoss, O=Red Hat, L=Raleigh, ST=NC, C=US
<jboss-web> <security-domain>cert-roles-domain</security-domain> </jboss-web>
<web-app> <!-- URL for secured portion of application--> <security-constraint> <web-resource-collection> <web-resource-name>secure</web-resource-name> <url-pattern>/secure/*</url-pattern> </web-resource-collection> <auth-constraint> <role-name>All</role-name> </auth-constraint> </security-constraint> <!-- Security roles referenced by this web application --> <security-role> <description>The role that is required to log in to the application</description> <role-name>All</role-name> </security-role> <login-config> <auth-method>CLIENT-CERT</auth-method> <realm-name>cert-roles-domain</realm-name> </login-config> </web-app>
/subsystem=security/security-domain= SECURITY_DOMAIN_NAME :write-attribute(name=cache-type,value= CACHE_TYPE )
/subsystem=security/security-domain=other:write-attribute(name=cache-type,value=infinispan)
/subsystem=security/security-domain= SECURITY_DOMAIN_NAME :list-cached-principals
/subsystem=security/security-domain= SECURITY_DOMAIN_NAME :flush-cache(principal= USERNAME )
/subsystem=security/security-domain= SECURITY_DOMAIN_NAME :flush-cache
/subsystem=security/security-domain= SECURITY_DOMAIN_NAME :undefine-attribute(name=cache-type)