Chapter 16. Login Modules

16.1. Using Modules

JBoss EAP 6 includes several bundled login modules suitable for most user management needs. JBoss EAP 6 can read user information from a relational database, an LDAP server, or flat files. In addition to these core login modules, JBoss EAP 6 provides other login modules that provide user information for very customized needs.
More login modules and their options can be found in Appendix A.1.

16.1.1. Password Stacking

Multiple login modules can be chained together in a stack, with each login module providing both the credentials verification and role assignment during authentication. This works for many use cases, but sometimes credentials verification and role assignment are split across multiple user management stores.
Section 16.1.4, “Ldap Login Module” describes how to combine LDAP and a relational database, allowing a user to be authenticated by either system. Consider the case where users are managed in a central LDAP server but application-specific roles are stored in the application's relational database. The password-stacking module option captures this relationship.
To use password stacking, each login module should set the <module-option> password-stacking attribute to useFirstPass. If a previous module configured for password stacking has authenticated the user, all the other stacking modules will consider the user authenticated and only attempt to provide a set of roles for the authorization step.
When password-stacking option is set to useFirstPass, this module first looks for a shared user name and password under the property names javax.security.auth.login.name and javax.security.auth.login.password respectively in the login module shared state map.
If found, these properties are used as the principal name and password. If not found, the principal name and password are set by this login module and stored under the property names javax.security.auth.login.name and javax.security.auth.login.password respectively.

Note

When using password stacking, set all modules to be required. This ensures that all modules are considered, and have the chance to contribute roles to the authorization process.

Example 16.1. Password Stacking Sample

This management CLI example shows how password stacking could be used.
/subsystem=security/security-domain=pwdStack/authentication=classic/login-module=Ldap:add( \
  code=Ldap, \
  flag=required, \
  module-options=[ \
    ("password-stacking"=>"useFirstPass"), \
    ... Ldap login module configuration
  ])
/subsystem=security/security-domain=pwdStack/authentication=classic/login-module=Database:add( \
  code=Database, \
  flag=required, \
  module-options=[ \
    ("password-stacking"=>"useFirstPass"), \
    ... Database login module configuration
  ])

16.1.2. Password Hashing

Most login modules must compare a client-supplied password to a password stored in a user management system. These modules generally work with plain text passwords, but can be configured to support hashed passwords to prevent plain text passwords from being stored on the server side.

Important

Red Hat JBoss Enterprise Application Platform Common Criteria certified release only supports SHA-256 for password hashing.

Example 16.2. Password Hashing

The following is a login module configuration that assigns unauthenticated users the principal name nobody and contains based64-encoded, SHA-256 hashes of the passwords in a usersb64.properties file. The usersb64.properties file is part of the deployment classpath.
/subsystem=security/security-domain=testUsersRoles:add
/subsystem=security/security-domain=testUsersRoles/authentication=classic:add
/subsystem=security/security-domain=testUsersRoles/authentication=classic/login-module=UsersRoles:add( \
  code=UsersRoles, \
  flag=required, \
  module-options=[ \
    ("usersProperties"=>"usersb64.properties"), \
    ("rolesProperties"=>"test-users-roles.properties"), \
    ("unauthenticatedIdentity"=>"nobody"), \
    ("hashAlgorithm"=>"SHA-256"), \
    ("hashEncoding"=>"base64") \
  ])
hashAlgorithm
Name of the java.security.MessageDigest algorithm to use to hash the password. There is no default so this option must be specified to enable hashing. Typical values are SHA-256, SHA-1 and MD5.
hashEncoding
String that specifies one of three encoding types: base64, hex or rfc2617. The default is base64.
hashCharset
Encoding character set used to convert the clear text password to a byte array. The platform default encoding is the default.
hashUserPassword
Specifies the hashing algorithm must be applied to the password the user submits. The hashed user password is compared against the value in the login module, which is expected to be a hash of the password. The default is true.
hashStorePassword
Specifies the hashing algorithm must be applied to the password stored on the server side. This is used for digest authentication, where the user submits a hash of the user password along with a request-specific tokens from the server to be compare. The hash algorithm (for digest, this would be rfc2617) is utilized to compute a server-side hash, which should match the hashed value sent from the client.
If you must generate passwords in code, the org.jboss.security.auth.spi.Util class provides a static helper method that will hash a password using the specified encoding. The following example produces a base64-encoded, MD5 hashed password.
String hashedPassword = Util.createPasswordHash("SHA-256",
 Util.BASE64_ENCODING, null, null, "password");
OpenSSL provides an alternative way to quickly generate hashed passwords at the command-line. The following example also produces a base64-encoded, SHA-256 hashed password. Here the password in plain text - password - is piped into the OpenSSL digest function then piped into another OpenSSL function to convert into base64-encoded format.
echo -n password | openssl dgst -sha256 -binary | openssl base64
In both cases, the hashed version of the password is the same: XohImNooBHFR0OVvjcYpJ3NgPQ1qq73WKhHvch0VQtg=. This value must be stored in the users' properties file specified in the security domain - usersb64.properties - in the example above.

16.1.3. Unauthenticated Identity

Not all requests are received in an authenticated format. unauthenticatedIdentity is a login module configuration option that assigns a specific identity (guest, for example) to requests that are made with no associated authentication information. This can be used to allow unprotected servlets to invoke methods on EJBs that do not require a specific role. Such a principal has no associated roles and so can only access either unsecured EJBs or EJB methods that are associated with the unchecked permission constraint.
  • unauthenticatedIdentity: This defines the principal name that should be assigned to requests that contain no authentication information.

16.1.4. Ldap Login Module

Ldap login module is a LoginModule implementation that authenticates against a Lightweight Directory Access Protocol (LDAP) server. Use the Ldap login module if your user name and credentials are stored in an LDAP server that is accessible using a Java Naming and Directory Interface (JNDI) LDAP provider.

Note

If you wish to use LDAP with the SPNEGO authentication or skip some of the authentication phases while using an LDAP server, consider using the AdvancedLdap login module chained with the SPNEGO login module or only the AdvancedLdap login module.
Distinguished Name (DN)
In Lightweight Directory Access Protocol (LDAP), the distinguished name uniquely identifies an object in a directory. Each distinguished name must have a unique name and location from all other objects, which is achieved using a number of attribute-value pairs (AVPs). The AVPs define information such as common names, organization unit, among others. The combination of these values results in a unique string required by the LDAP.

Note

This login module also supports unauthenticated identity and password stacking.
The LDAP connectivity information is provided as configuration options that are passed through to the environment object used to create JNDI initial context. The standard LDAP JNDI properties used include the following:
java.naming.factory.initial
InitialContextFactory implementation class name. This defaults to the Sun LDAP provider implementation com.sun.jndi.ldap.LdapCtxFactory.
java.naming.provider.url
LDAP URL for the LDAP server.
java.naming.security.authentication
Security protocol level to use. The available values include none, simple, and strong. If the property is undefined, the behavior is determined by the service provider.
java.naming.security.protocol
Transport protocol to use for secure access. Set this configuration option to the type of service provider (for example, SSL). If the property is undefined, the behavior is determined by the service provider.
java.naming.security.principal
Specifies the identity of the Principal for authenticating the caller to the service. This is built from other properties as described below.
java.naming.security.credentials
Specifies the credentials of the Principal for authenticating the caller to the service. Credentials can take the form of a hashed password, a clear-text password, a key, or a certificate. If the property is undefined, the behavior is determined by the service provider.
For details of Ldap login module configuration options see Section A.1, “Included Authentication Modules”.

Note

In certain directory schemas (e.g., Microsoft Active Directory), role attributes in the user object are stored as DNs to role objects instead of simple names. For implementations that use this schema type, roleAttributeIsDN must be set to true.
User authentication is performed by connecting to the LDAP server, based on the login module configuration options. Connecting to the LDAP server is done by creating an InitialLdapContext with an environment composed of the LDAP JNDI properties described previously in this section.
The Context.SECURITY_PRINCIPAL is set to the distinguished name of the user obtained by the callback handler in combination with the principalDNPrefix and principalDNSuffix option values, and the Context.SECURITY_CREDENTIALS property is set to the respective String password.
Once authentication has succeeded (InitialLdapContext instance is created), the user's roles are queried by performing a search on the rolesCtxDN location with search attributes set to the roleAttributeName and uidAttributeName option values. The roles names are obtaining by invoking the toString method on the role attributes in the search result set.

Example 16.3. LDAP Login Module Security Domain

This management CLI example shows how to use the parameters in a security domain authentication configuration.
/subsystem=security/security-domain=testLDAP:add(cache-type=default)
/subsystem=security/security-domain=testLDAP/authentication=classic:add
/subsystem=security/security-domain=testLDAP/authentication=classic/login-module=Ldap:add( \
  code=Ldap, \
  flag=required, \
  module-options=[ \
    ("java.naming.factory.initial"=>"com.sun.jndi.ldap.LdapCtxFactory"), \
    ("java.naming.provider.url"=>"ldap://ldaphost.jboss.org:1389/"), \
    ("java.naming.security.authentication"=>"simple"), \
    ("principalDNPrefix"=>"uid="), \
    ("principalDNSuffix"=>",ou=People,dc=jboss,dc=org"), \
    ("rolesCtxDN"=>"ou=Roles,dc=jboss,dc=org"), \
    ("uidAttributeID"=>"member"), \
    ("matchOnUserDN"=>true), \
    ("roleAttributeID"=>"cn"), \
    ("roleAttributeIsDN"=>false) \
  ])
The java.naming.factory.initial, java.naming.factory.url and java.naming.security options in the testLDAP security domain configuration indicate the following conditions:
  • The Sun LDAP JNDI provider implementation will be used
  • The LDAP server is located on host ldaphost.jboss.org on port 1389
  • The LDAP simple authentication method will be use to connect to the LDAP server.
The login module attempts to connect to the LDAP server using a Distinguished Name (DN) representing the user it is trying to authenticate. This DN is constructed from the passed principalDNPrefix, the user name of the user and the principalDNSuffix as described above. In Example 16.4, “LDIF File Example”, the user name jsmith would map to uid=jsmith,ou=People,dc=jboss,dc=org.

Note

The example assumes the LDAP server authenticates users using the userPassword attribute of the user's entry (theduke in this example). Most LDAP servers operate in this manner, however if your LDAP server handles authentication differently you must ensure LDAP is configured according to your production environment requirements.
Once authentication succeeds, the roles on which authorization will be based are retrieved by performing a subtree search of the rolesCtxDN for entries whose uidAttributeID match the user. If matchOnUserDN is true, the search will be based on the full DN of the user. Otherwise the search will be based on the actual user name entered. In this example, the search is under ou=Roles,dc=jboss,dc=org for any entries that have a member attribute equal to uid=jsmith,ou=People,dc=jboss,dc=org. The search would locate cn=JBossAdmin under the roles entry.
The search returns the attribute specified in the roleAttributeID option. In this example, the attribute is cn. The value returned would be JBossAdmin, so the jsmith user is assigned to the JBossAdmin role.
A local LDAP server often provides identity and authentication services, but is unable to use authorization services. This is because application roles do not always map well onto LDAP groups, and LDAP administrators are often hesitant to allow external application-specific data in central LDAP servers. The LDAP authentication module is often paired with another login module, such as the database login module, that can provide roles more suitable to the application being developed.
An LDAP Data Interchange Format (LDIF) file representing the structure of the directory this data operates against is shown in Example 16.4, “LDIF File Example”.
LDAP Data Interchange Format (LDIF)
Plain text data interchange format used to represent LDAP directory content and update requests. Directory content is represented as one record for each object or update request. Content consists of add, modify, delete, and rename requests.

Example 16.4. LDIF File Example

dn: dc=jboss,dc=org
objectclass: top
objectclass: dcObject
objectclass: organization
dc: jboss
o: JBoss

dn: ou=People,dc=jboss,dc=org
objectclass: top
objectclass: organizationalUnit
ou: People

dn: uid=jsmith,ou=People,dc=jboss,dc=org
objectclass: top
objectclass: uidObject
objectclass: person
uid: jsmith
cn: John
sn: Smith
userPassword: theduke

dn: ou=Roles,dc=jboss,dc=org
objectclass: top
objectclass: organizationalUnit
ou: Roles

dn: cn=JBossAdmin,ou=Roles,dc=jboss,dc=org
objectclass: top
objectclass: groupOfNames
cn: JBossAdmin
member: uid=jsmith,ou=People,dc=jboss,dc=org
description: the JBossAdmin group

16.1.5. LdapExtended Login Module

Distinguished Name (DN)
In Lightweight Directory Access Protocol (LDAP), the distinguished name uniquely identifies an object in a directory. Each distinguished name must have a unique name and location from all other objects, which is achieved using a number of attribute-value pairs (AVPs). The AVPs define information such as common names, organization unit, among others. The combination of these values results in a unique string required by the LDAP.
The LdapExtended (org.jboss.security.auth.spi.LdapExtLoginModule) searches for the user to bind, as well as the associated roles, for authentication. The roles query recursively follows DNs to navigate a hierarchical role structure.
The LoginModule options include whatever options are supported by the chosen LDAP JNDI provider supports. Examples of standard property names are:
  • Context.INITIAL_CONTEXT_FACTORY = "java.naming.factory.initial"
  • Context.SECURITY_PROTOCOL = "java.naming.security.protocol"
  • Context.PROVIDER_URL = "java.naming.provider.url"
  • Context.SECURITY_AUTHENTICATION = "java.naming.security.authentication"
  • Context.REFERRAL = "java.naming.referral"
Login module implementation logic follows the order below:
  1. The initial LDAP server bind is authenticated using the bindDN and bindCredential properties. The bindDN is a user with permissions 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 property.
  2. The resulting userDN is authenticated by binding to the LDAP server using the userDN as the InitialLdapContext environment Context.SECURITY_PRINCIPAL. The Context.SECURITY_CREDENTIALS property is either set to the String password obtained by the callback handler.
  3. If this is successful, the associated user roles are queried using the rolesCtxDN, roleAttributeID, roleAttributeIsDN, roleNameAttributeID, and roleFilter options.
For details of LdapExtended login module options see Section A.1, “Included Authentication Modules”.
LDAP Structure Example

Figure 16.1. LDAP Structure Example

Example 16.5. Example 2 LDAP Configuration

version: 1
dn: o=example2,dc=jboss,dc=org
objectClass: top
objectClass: organization
o: example2

dn: ou=People,o=example2,dc=jboss,dc=org
objectClass: top
objectClass: organizationalUnit
ou: People

dn: uid=jduke,ou=People,o=example2,dc=jboss,dc=org
objectClass: top
objectClass: uidObject
objectClass: person
objectClass: inetOrgPerson
cn: Java Duke
employeeNumber: judke-123
sn: Duke
uid: jduke
userPassword:: dGhlZHVrZQ==

dn: uid=jduke2,ou=People,o=example2,dc=jboss,dc=org
objectClass: top
objectClass: uidObject
objectClass: person
objectClass: inetOrgPerson
cn: Java Duke2
employeeNumber: judke2-123
sn: Duke2
uid: jduke2
userPassword:: dGhlZHVrZTI=

dn: ou=Roles,o=example2,dc=jboss,dc=org
objectClass: top
objectClass: organizationalUnit
ou: Roles

dn: uid=jduke,ou=Roles,o=example2,dc=jboss,dc=org
objectClass: top
objectClass: groupUserEx
memberOf: cn=Echo,ou=Roles,o=example2,dc=jboss,dc=org
memberOf: cn=TheDuke,ou=Roles,o=example2,dc=jboss,dc=org
uid: jduke

dn: uid=jduke2,ou=Roles,o=example2,dc=jboss,dc=org
objectClass: top
objectClass: groupUserEx
memberOf: cn=Echo2,ou=Roles,o=example2,dc=jboss,dc=org
memberOf: cn=TheDuke2,ou=Roles,o=example2,dc=jboss,dc=org
uid: jduke2

dn: cn=Echo,ou=Roles,o=example2,dc=jboss,dc=org
objectClass: top
objectClass: groupOfNames
cn: Echo
description: the echo role
member: uid=jduke,ou=People,dc=jboss,dc=org

dn: cn=TheDuke,ou=Roles,o=example2,dc=jboss,dc=org
objectClass: groupOfNames
objectClass: top
cn: TheDuke
description: the duke role
member: uid=jduke,ou=People,o=example2,dc=jboss,dc=org

dn: cn=Echo2,ou=Roles,o=example2,dc=jboss,dc=org
objectClass: top
objectClass: groupOfNames
cn: Echo2
description: the Echo2 role
member: uid=jduke2,ou=People,dc=jboss,dc=org

dn: cn=TheDuke2,ou=Roles,o=example2,dc=jboss,dc=org
objectClass: groupOfNames
objectClass: top
cn: TheDuke2
description: the duke2 role
member: uid=jduke2,ou=People,o=example2,dc=jboss,dc=org

dn: cn=JBossAdmin,ou=Roles,o=example2,dc=jboss,dc=org
objectClass: top
objectClass: groupOfNames
cn: JBossAdmin
description: the JBossAdmin group
member: uid=jduke,ou=People,dc=jboss,dc=org
The module configuration for this LDAP structure example is outlined in the following management CLI command.

/subsystem=security/security-domain=testLdapExample2/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://ldaphost.jboss.org"), \
    ("java.naming.security.authentication"=>"simple"), \
    ("bindDN"=>"cn=Root,dc=jboss,dc=org"), \
    ("bindCredential"=>"secret1"), \
    ("baseCtxDN"=>"ou=People,o=example2,dc=jboss,dc=org"), \
    ("baseFilter"=>"(uid={0})"), \
    ("rolesCtxDN"=>"ou=Roles,o=example2,dc=jboss,dc=org"), \
    ("roleFilter"=>"(uid={0})"), \
    ("roleAttributeIsDN"=>"true"), \
    ("roleAttributeID"=>"memberOf"), \
    ("roleNameAttributeID"=>"cn") \
  ])

Example 16.6. Example 3 LDAP Configuration


dn: o=example3,dc=jboss,dc=org
objectclass: top
objectclass: organization
o: example3

dn: ou=People,o=example3,dc=jboss,dc=org
objectclass: top
objectclass: organizationalUnit
ou: People

dn: uid=jduke,ou=People,o=example3,dc=jboss,dc=org
objectclass: top
objectclass: uidObject
objectclass: person
objectClass: inetOrgPerson
uid: jduke
employeeNumber: judke-123
cn: Java Duke
sn: Duke
userPassword: theduke

dn: ou=Roles,o=example3,dc=jboss,dc=org
objectClass: top
objectClass: organizationalUnit
ou: Roles

dn: uid=jduke,ou=Roles,o=example3,dc=jboss,dc=org
objectClass: top
objectClass: groupUserEx
memberOf: cn=Echo,ou=Roles,o=example3,dc=jboss,dc=org
memberOf: cn=TheDuke,ou=Roles,o=example3,dc=jboss,dc=org
uid: jduke

dn: cn=Echo,ou=Roles,o=example3,dc=jboss,dc=org
objectClass: top
objectClass: groupOfNames
cn: Echo
description: the JBossAdmin group
member: uid=jduke,ou=People,o=example3,dc=jboss,dc=org

dn: cn=TheDuke,ou=Roles,o=example3,dc=jboss,dc=org
objectClass: groupOfNames
objectClass: top
cn: TheDuke
member: uid=jduke,ou=People,o=example3,dc=jboss,dc=org

The module configuration for this LDAP structure example is outlined in the following management CLI command.

/subsystem=security/security-domain=testLdapExample3/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://ldaphost.jboss.org"), \
    ("java.naming.security.authentication"=>"simple"), \
    ("bindDN"=>"cn=Root,dc=jboss,dc=org"), \
    ("bindCredential"=>"secret1"), \
    ("baseCtxDN"=>"ou=People,o=example3,dc=jboss,dc=org"), \
    ("baseFilter"=>"(cn={0})"), \
    ("rolesCtxDN"=>"ou=Roles,o=example3,dc=jboss,dc=org"), \
    ("roleFilter"=>"(member={1})"), \
    ("roleAttributeID"=>"cn") \
  ])

Example 16.7. Example 4 LDAP Configuration


dn: o=example4,dc=jboss,dc=org
objectclass: top
objectclass: organization
o: example4

dn: ou=People,o=example4,dc=jboss,dc=org
objectclass: top
objectclass: organizationalUnit
ou: People

dn: uid=jduke,ou=People,o=example4,dc=jboss,dc=org
objectClass: top
objectClass: uidObject
objectClass: person
objectClass: inetOrgPerson
cn: Java Duke
employeeNumber: jduke-123
sn: Duke
uid: jduke
userPassword:: dGhlZHVrZQ==

dn: ou=Roles,o=example4,dc=jboss,dc=org
objectClass: top
objectClass: organizationalUnit
ou: Roles

dn: cn=RG1,ou=Roles,o=example4,dc=jboss,dc=org
objectClass: groupOfNames
objectClass: top
cn: RG1
member: cn=empty

dn: cn=RG2,cn=RG1,ou=Roles,o=example4,dc=jboss,dc=org
objectClass: groupOfNames
objectClass: top
cn: RG2
member: cn=RG1,ou=Roles,o=example4,dc=jboss,dc=org
member: uid=jduke,ou=People,o=example4,dc=jboss,dc=org

dn: cn=RG3,cn=RG1,ou=Roles,o=example4,dc=jboss,dc=org
objectClass: groupOfNames
objectClass: top
cn: RG3
member: cn=RG1,ou=Roles,o=example4,dc=jboss,dc=org

dn: cn=R1,ou=Roles,o=example4,dc=jboss,dc=org
objectClass: groupOfNames
objectClass: top
cn: R1
member: cn=RG2,cn=RG1,ou=Roles,o=example4,dc=jboss,dc=org

dn: cn=R2,ou=Roles,o=example4,dc=jboss,dc=org
objectClass: groupOfNames
objectClass: top
cn: R2
member: cn=RG2,cn=RG1,ou=Roles,o=example4,dc=jboss,dc=org

dn: cn=R3,ou=Roles,o=example4,dc=jboss,dc=org
objectClass: groupOfNames
objectClass: top
cn: R3
member: cn=RG2,cn=RG1,ou=Roles,o=example4,dc=jboss,dc=org
member: cn=RG3,cn=RG1,ou=Roles,o=example4,dc=jboss,dc=org

dn: cn=R4,ou=Roles,o=example4,dc=jboss,dc=org
objectClass: groupOfNames
objectClass: top
cn: R4
member: cn=RG3,cn=RG1,ou=Roles,o=example4,dc=jboss,dc=org

dn: cn=R5,ou=Roles,o=example4,dc=jboss,dc=org
objectClass: groupOfNames
objectClass: top
cn: R5
member: cn=RG3,cn=RG1,ou=Roles,o=example4,dc=jboss,dc=org
member: uid=jduke,ou=People,o=example4,dc=jboss,dc=org
The module configuration for this LDAP structure example is outlined in the code sample.

/subsystem=security/security-domain=testLdapExample4/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://ldaphost.jboss.org"), \
    ("java.naming.security.authentication"=>"simple"), \
    ("bindDN"=>"cn=Root,dc=jboss,dc=org"), \
    ("bindCredential"=>"secret1"), \
    ("baseCtxDN"=>"ou=People,o=example4,dc=jboss,dc=org"), \
    ("baseFilter"=>"(cn={0})"), \
    ("rolesCtxDN"=>"ou=Roles,o=example4,dc=jboss,dc=org"), \
    ("roleFilter"=>"(member={1})"), \
    ("roleRecursion"=>"1"), \
    ("roleAttributeID"=>"memberOf") \
  ])

Example 16.8. Default Active Directory Configuration

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.

/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"=>"JBOSS\searchuser"), \
    ("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") \
  ])

Example 16.9. Recursive Roles Active Directory 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.

/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"=>"JBOSS\searchuser"), \
    ("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") \
  ])

16.1.6. UsersRoles Login Module

UsersRoles login module is a simple login module that supports multiple users and user roles loaded from Java properties files. The default username-to-password mapping filename is users.properties and the default username-to-roles mapping filename is roles.properties.
For details of UsersRoles login module options see Section A.1, “Included Authentication Modules” .
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 Java EE deployment (for example, into the WEB-INF/classes folder in the WAR archive), or into any directory on the server classpath. 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.

Example 16.10. UserRoles Login Module

/subsystem=security/security-domain=ejb3-sampleapp/authentication=classic/login-module=UsersRoles:add( \
  code=UsersRoles, \
  flag=required, \
  module-options=[ \
    ("usersProperties"=>"ejb3-sampleapp-users.properties"), \
    ("rolesProperties"=>"ejb3-sampleapp-roles.properties") \
  ])
In Example 16.10, “UserRoles Login Module”, the ejb3-sampleapp-users.properties file uses a username=password format with each user entry on a separate line:
username1=password1
username2=password2
...
The ejb3-sampleapp-roles.properties file referenced in Example 16.10, “UserRoles Login Module” uses the pattern username=role1,role2, with an optional group name value. For example:
username1=role1,role2,...
username1.RoleGroup1=role3,role4,...
username2=role1,role3,...
The user name.XXX property name pattern present in ejb3-sampleapp-roles.properties is used to assign the user name roles to a particular named group of roles where the XXX portion of the property name is the group name. The user name=... form is an abbreviation for user name.Roles=..., where the Roles group name is the standard name the JBossAuthorizationManager expects to contain the roles which define the permissions of users.
The following would be equivalent definitions for the jduke user name:
jduke=TheDuke,AnimatedCharacter
jduke.Roles=TheDuke,AnimatedCharacter

16.1.7. Database Login Module

The Database login module is a Java Database Connectivity-based (JDBC) login module that supports authentication and role mapping. Use this login module if you have your user name, password and role information stored in a relational database.

Note

This module supports password stacking, password hashing and unauthenticated identity.
The Database login module is based on two logical tables:
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 you 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 notion, 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
INSERT INTO Principals VALUES('java', 'echoman')
INSERT INTO Roles VALUES('java', 'Echo', 'Roles')
INSERT INTO Roles VALUES('java', 'caller_java', 'CallerPrincipal')
For details of Database login module options see Section A.1, “Included Authentication Modules”.
An example Database login module configuration could be constructed as follows:
CREATE TABLE Users(username VARCHAR(64) PRIMARY KEY, passwd VARCHAR(64))
CREATE TABLE UserRoles(username VARCHAR(64), role VARCHAR(32))
A corresponding login module configuration in a security domain:
/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=?") \
  ])

16.1.8. Certificate Login Module

Certificate login module authenticates users based on X509 certificates. A typical use case for this login module is CLIENT-CERT authentication in the web tier.
This login module only performs authentication: you must combine it with another login module capable of acquiring authorization roles to completely define access to a secured web or EJB component. Two subclasses of this login module, CertRolesLoginModule and DatabaseCertLoginModule extend the behavior to obtain the authorization roles from either a properties file or database.
For details of Certificate login module options see Section A.1, “Included Authentication Modules”.
The Certificate login module needs a KeyStore to perform user validation. This is obtained from a JSSE configuration of linked security domain as shown in the following configuration fragment:
/subsystem=security/security-domain=trust-domain:add
/subsystem=security/security-domain=trust-domain/jsse=classic:add( \
  truststore={ \
    password=>pass1234, \
    url=>/home/jbosseap/trusted-clients.jks \
  })

/subsystem=security/security-domain=testCert:add
/subsystem=security/security-domain=testCert/authentication=classic:add
/subsystem=security/security-domain=testCert/authentication=classic/login-module=Certificate:add( \
  code=Certificate, \
  flag=required, \
  module-options=[ \
    ("securityDomain"=>"trust-domain"), \
  ])

Procedure 16.1. Secure Web Applications with Certificates and Role-based Authorization

This procedure describes how to secure a web application, such as the user-app.war, using client certificates and role-based authorization. In this example the CertificateRoles login module is used for authentication and authorization. Both the trusted-clients.keystore and the app-roles.properties require an entry that maps to the principal associated with the client certificate.
By default, the principal is created using the client certificate distinguished name, such as the DN specified in Example 16.11, “Certificate Example”.
  1. Declare Resources and Roles

    Modify web.xml to declare the resources to be secured along with the allowed roles and security domain to be used for authentication and authorization.
    
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
            version="3.0">
    
            <security-constraint>
                    <web-resource-collection>
                            <web-resource-name>Protect App</web-resource-name>
                            <url-pattern>/*</url-pattern>
                    </web-resource-collection>
                    <auth-constraint>
                            <role-name>Admin</role-name>
                    </auth-constraint>
            </security-constraint>
    
            <login-config>
                    <auth-method>CLIENT-CERT</auth-method>
                    <realm-name>Secured area</realm-name>
            </login-config>
    
            <security-role>
                    <role-name>Admin</role-name>
            </security-role>
    </web-app>
    
    
  2. Specify the Security Domain

    In the jboss-web.xml file, specify the required security domain.
    
    <jboss-web>
      <security-domain>app-sec-domain</security-domain>
    </jboss-web>
    
    
  3. Configure Login Module

    Define the login module configuration for the app-sec-domain domain you just specified using the management CLI.
    [
    /subsystem=security/security-domain=trust-domain:add
    /subsystem=security/security-domain=trust-domain/jsse=classic:add( \
      truststore={ \
        password=>pass1234, \
        url=>/home/jbosseap/trusted-clients.jks \
      })
    
    /subsystem=security/security-domain=app-sec-domain:add
    /subsystem=security/security-domain=app-sec-domain/authentication=classic:add
    /subsystem=security/security-domain=app-sec-domain/authentication=classic/login-module=CertificateRoles:add( \
      code=CertificateRoles, \
      flag=required, \
      module-options=[ \
        ("securityDomain"=>"trust-domain"), \
        ("rolesProperties"=>"app-roles.properties") \
      ])
    

Example 16.11. Certificate Example

[conf]$ keytool -printcert -file valid-client-cert.crt
Owner: CN=valid-client, OU=Security QE, OU=JBoss, O=Red Hat, C=CZ
Issuer: CN=EAP Certification Authority, OU=Security QE, OU=JBoss, O=Red Hat, C=CZ
Serial number: 2
Valid from: Mon Mar 24 18:21:55 CET 2014 until: Tue Mar 24 18:21:55 CET 2015
Certificate fingerprints:
         MD5:  0C:54:AE:6E:29:ED:E4:EF:46:B5:14:30:F2:E0:2A:CB
         SHA1: D6:FB:19:E7:11:28:6C:DE:01:F2:92:2F:22:EF:BB:5D:BF:73:25:3D
         SHA256: CD:B7:B1:72:A3:02:42:55:A3:1C:30:E1:A6:F0:20:B0:2C:0F:23:4F:7A:8E:2F:2D:FA:AF:55:3E:A7:9B:2B:F4
         Signature algorithm name: SHA1withRSA
         Version: 3
The trusted-clients.keystore would need the certificate in Example 16.11, “Certificate Example” stored with an alias of CN=valid-client, OU=Security QE, OU=JBoss, O=Red Hat, C=CZ. The app-roles.properties must have the same entry. Since the DN contains characters that are normally treated as delimiters, you must escape the problem characters using a backslash ('\') as illustrated below.
# A sample app-roles.properties file
CN\=valid-client,\ OU\=Security\ QE,\ OU\=JBoss,\ O\=Red\ Hat,\ C\=CZ

16.1.9. Identity Login Module

Identity login module is a simple login module that associates a hard-coded user name to any subject authenticated against the module. It creates a SimplePrincipal instance using the name specified by the principal option.

Note

This module supports password stacking.
This login module is useful when you need to provide a fixed identity to a service, and in development environments when you want to test the security associated with a given principal and associated roles.
For details of Identity login module options see Section A.1, “Included Authentication Modules”.
A sample security domain configuration is described below. It authenticates all users as the principal named jduke and assigns role names of TheDuke, and AnimatedCharacter:.
/subsystem=security/security-domain=testIdentity:add
/subsystem=security/security-domain=testIdentity/authentication=classic:add
/subsystem=security/security-domain=testIdentity/authentication=classic/login-module=Identity:add( \
  code=Identity, \
  flag=required, \
  module-options=[ \
    ("principal"=>"jduke"), \
    ("roles"=>"TheDuke,AnimatedCharacter") \
  ])

16.1.10. RunAs Login Module

RunAs login module is a helper module that pushes a run as role onto the stack for the duration of the login phase of authentication, then pops the run as role from the stack in either the commit or abort phase.
The purpose of this login module is to provide a role for other login modules that must access secured resources in order to perform their authentication (for example, a login module that accesses a secured EJB). RunAs login module must be configured ahead of the login modules that require a run as role established.
For details of RunAs login module options see Section A.1, “Included Authentication Modules”.

16.1.10.1. RunAsIdentity Creation

In order for JBoss EAP 6 to secure access to EJB methods, the identity of the user must be known at the time the method call is made.
A user's identity in the server is represented either by a javax.security.auth.Subject instance or an org.jboss.security.RunAsIdentity instance. Both these classes store one or more principals that represent the identity and a list of roles that the identity possesses. In the case of the javax.security.auth.Subject a list of credentials is also stored.
In the <assembly-descriptor> section of the ejb-jar.xml deployment descriptor, you specify one or more roles that a user must have to access the various EJB methods. A comparison of these lists reveals whether the user has one of the roles necessary to access the EJB method.

Example 16.12. org.jboss.security.RunAsIdentity Creation

In the ejb-jar.xml file, you specify a <security-identity> element with a <run-as> role defined as a child of the <session> element.
<session>
   ...
   <security-identity>
      <run-as>
         <role-name>Admin</role-name>
      </run-as>
   </security-identity>
   ...
</session>
This declaration signifies that an Admin RunAsIdentity role must be created.
To name a principal for the Admin role, you define a <run-as-principal> element in the jboss-ejb3.xml file.

<jboss:ejb-jar
        xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:jboss="http://www.jboss.com/xml/ns/javaee"
        xmlns:s="urn:security:1.1"
        version="3.1" impl-version="2.0">
    <assembly-descriptor>
        <s:security>
            <ejb-name>WhoAmIBean</ejb-name>
            <s:run-as-principal>John</s:run-as-principal>
        </s:security>
    </assembly-descriptor>
</jboss:ejb-jar>

The <security-identity> element in both the ejb-jar.xml and <security> element in the jboss-ejb3.xml files are parsed at deployment time. The <run-as> role name and the <run-as-principal> name are then stored in the org.jboss.metadata.ejb.spec.SecurityIdentityMetaData class.

Example 16.13. Assigning multiple roles to a RunAsIdentity

You can assign more roles to RunAsIdentity by mapping roles to principals in the jboss-ejb3.xml deployment descriptor <assembly-descriptor> element group.

<jboss:ejb-jar xmlns:sr="urn:security-role"
        ...>
        <assembly-descriptor>
            ...
                <sr:security-role>
                        <sr:role-name>Support</sr:role-name>
                        <sr:principal-name>John</sr:principal-name>
                        <sr:principal-name>Jill</sr:principal-name>
                        <sr:principal-name>Tony</sr:principal-name>
                </sr:security-role>
        </assembly-descriptor>
</jboss:ejb-jar>

In Example 16.12, “org.jboss.security.RunAsIdentity Creation”, the <run-as-principal> of John was created. The configuration in this example extends the Admin role, by adding the Support role. The new role contains extra principals, including the originally defined principal John.
The <security-role> element in both the ejb-jar.xml and jboss-ejb3.xml files are parsed at deployment time. The <role-name> and the <principal-name> data is stored in the org.jboss.metadata.ejb.spec.SecurityIdentityMetaData class.

16.1.11. Client Login Module

Client login module (org.jboss.security.ClientLoginModule) is an implementation of LoginModule for use by JBoss clients when establishing caller identity and credentials. This creates a new SecurityContext assigns it a principal and a credential and sets the SecurityContext to the ThreadLocal security context.
Client login module is the only supported mechanism for a client to establish the current thread's caller. Both stand-alone client applications, and server environments (acting as JBoss EJB clients where the security environment has not been configured to use the EAP security subsystem transparently) must use Client login module.
Note that this login module does not perform any authentication. It merely copies the login information provided to it into the server EJB invocation layer for subsequent authentication on the server. If you need to perform client-side authentication of users you would need to configure another login module in addition to the Client login module.
For details of Client login module options see Section A.1, “Included Authentication Modules”.

16.1.12. SPNEGO Login Module

SPNEGO login module (org.jboss.security.negotiation.spnego.SPNEGOLoginModule) is an implementation of LoginModule that establishes caller identity and credentials with a KDC. The module implements SPNEGO (Simple and Protected GSSAPI Negotiation mechanism) and is a part of the JBoss Negotiation project. This authentication can be used in the chained configuration with the AdvancedLdap login module to allow cooperation with an LDAP server.
For details of SPNEGO login module options see Section A.1, “Included Authentication Modules”.
The JBoss Negotiation module is not included as a standard dependency for deployed applications. To use the SPNEGO or AdvancedLdap login modules in your project, you must add the dependency manually by editing the META-INF/jboss-deployment-structure.xml deployment descriptor file.

Example 16.14. Add JBoss Negotiation Module as a Dependency


<jboss-deployment-structure>
  <deployment>
    <dependencies>
      <module name="org.jboss.security.negotiation" />
    </dependencies>
  </deployment>
</jboss-deployment-structure>

16.1.13. RoleMapping Login Module

RoleMapping login module supports mapping roles, that are the end result of the authentication process, to one or more declarative roles. For example, if the authentication process has determined that the user "A" has the roles "ldapAdmin" and "testAdmin", and the declarative role defined in the web.xml or ejb-jar.xml file for access is admin, then this login module maps the admin roles to the user A.
For details of RoleMapping login module options see Section A.1, “Included Authentication Modules”.
The RoleMapping login module must be defined as an optional module to a login module configuration as it alters mapping of the previously mapped roles.

Example 16.15. Defining mapped roles

/subsystem=security/security-domain=test-domain-2/:add
/subsystem=security/security-domain=test-domain-2/authentication=classic:add
/subsystem=security/security-domain=test-domain-2/authentication=classic/login-module=test-2-lm/:add(\
flag=required,\
code=UsersRoles,\
module-options=[("usersProperties"=>"users.properties"),("rolesProperties"=>"roles.properties")]\
)
/subsystem=security/security-domain=test-domain-2/authentication=classic/login-module=test2-map/:add(\
flag=optional,\
code=RoleMapping,\
module-options=[("rolesProperties"=>"rolesMapping-roles.properties")]\
)
Another example achieving the same result, but using the mapping module. This is the preferred method of role mapping:

Example 16.16. Preferred method of defining mapped roles

/subsystem=security/security-domain=test-domain-2/:add
/subsystem=security/security-domain=test-domain-2/authentication=classic:add
/subsystem=security/security-domain=test-domain-2/authentication=classic/login-module=test-2-lm/:add(\
flag=required,\
code=UsersRoles,\
module-options=[("usersProperties"=>"users.properties"),("rolesProperties"=>"roles.properties")]\
)
/subsystem=security/security-domain=test-domain-2/mapping=classic/mapping-module=test2-map/:add(\
code=PropertiesRoles,type=role,\
module-options=[("rolesProperties"=>"rolesMapping-roles.properties")]\
)

Example 16.17. Properties File used by a RoleMappingLoginModule

ldapAdmin=admin, testAdmin
If the authenticated subject contains role ldapAdmin, then the roles admin and testAdmin are added to or substitute the authenticated subject depending on the replaceRole property value.

16.1.14. bindCredential Module Option

The bindCredential module option is used to store the credentials for the DN and can be used by several login and mapping modules. There are several methods for obtaining the password.

Plaintext in a management CLI command.
The password for the bindCredential module may be provided in plaintext, in a management CLI command. For example: ("bindCredential"=>"secret1"). For security reasons, the password should be encrypted using the JBoss EAP vault mechanism.
Use an external command.
To obtain the password from the output of an external command, use the format {EXT}... where the ... is the external command. The first line of the command output is used as the password.
To improve performance, the {EXTC[:expiration_in_millis]} variant caches the password for a specified number of milliseconds. By default the cached password does not expire. If the value 0 (zero) is specified, the cached credentials do not expire.
The EXTC variant is only supported by the LdapExtended login module.

Example 16.18. Obtain a password from an external command

{EXT}cat /mysecretpasswordfile

Example 16.19. Obtain a password from an external file and cache it for 500 milliseconds

{EXTC:500}cat /mysecretpasswordfile