Integrate security infrastructures with JBossSX

JBossSX uses JAAS to integrate application servers and security infrastructures

1 2 3 4 5 Page 2
Page 2 of 5

Specify the security domain in JBoss

The J2EE security elements I have covered describe only the security requirements from the application's perspective. Since J2EE security elements declare logical roles, the application deployer maps the roles from the application domain onto the deployment environment. The EJB specification omits these application-server-specific details. In JBoss, mapping the application roles onto the deployment environment entails specifying a security manager that implements the J2EE security model. Figure 3 shows the JBoss-specific EJB and Web application deployment descriptor's security-related elements.

Figure 3. The JBoss-specific EJB and Web deployment descriptor security elements Click on thumbnail to view full-size image.

Use the

security-domain

element to identify the Java Naming and Directory Interface (JNDI) name of the security manager interface implementation that JBoss uses for the EJB and Web containers. You may specify

security-domain

as an EJB-level element to only set security for one or more EJBs when

security-domain

is not a top-level element, or when

security-domain

is a top-level element and you want to override it. The

security-proxy

element identifies a custom security interceptor that allows per-request security checks outside the scope of the EJB declarative security model without embedding security logic into the EJB implementation. I won't go into detail about that JBoss-specific feature, as this article focuses on using JAAS to implement the standard declarative security model. A JBoss security manager implementation requires the

org.jboss.security.EJBSecurityManager

and

org.jboss.security.RealmMapping

interfaces presented in Figure 4.

Figure 4. JBoss security manager interfaces Click on thumbnail to view full-size image.

For the remainder of this article, I focus on the JBossSX org.jboss.security.plugins.JaasSecurityManager, a JAAS-based implementation of the security manager interfaces. But first, I'll present a brief introduction to JAAS.

What is JAAS?

The JAAS 1.0 API consists of a set of Java packages for the user authentication and authorization. It implements a Java version of the standard Pluggable Authentication Module (

PAM

) framework and compatibly extends the Java 2 Platform's access control architecture to support user-based authorization. JAAS was first released as an extension package for JDK 1.3 and is bundled with the current JDK 1.4 beta. As the JBossSX framework only uses the authentication aspect of JAAS to implement the declarative-role-based J2EE security model, this introduction focuses only on that topic. For a more comprehensive overview, see the JAAS material in

Resources

. I took much of this section's material from the

JAAS 1.0 Developers Guide

. JAAS authentication is performed in a pluggable fashion. This permits Java applications to remain independent from underlying authentication technologies and allows the JBossSX security manager to work in different security infrastructures. Integration with a security infrastructure can succeed without changing the JBossSX security manager. Authentication consists of instantiating a

LoginContext

object, which passes the name of a

Configuration

entry to determine which

LoginModule

will be created. The

LoginModule

s define the authentication technology.

LoginModule

s often use a username and password to verify identity, but any form of identity and identity verification will work.

The JAAS core classes

The JAAS core classes break down into three categories:

common, authentication,

and

authorization.

The list below presents the common and authentication classes, since the JBossSX functionality covered in this article uses only these classes.

  • Common classes:
    • Subject (javax.security.auth.Subject)
    • Principal (java.security.Principal)
  • Authentication classes:
    • Callback (javax.security.auth.callback.Callback)
    • CallbackHandler (javax.security.auth.callback.CallbackHandler)
    • Configuration (javax.security.auth.login.Configuration)
    • LoginContext (javax.security.auth.login.LoginContext)
    • LoginModule (javax.security.auth.spi.LoginModule)

Subject and Principal

To authorize access to resources, applications first need to authenticate the request's source. The JAAS framework defines the term

Subject

to represent the request's source.

Subject

is the key JAAS class; it represents information for a single entity, such as a person or service. It encompasses the entity's principals, public credentials, and private credentials. The JAAS APIs use the existing Java 2

java.security.Principal

interface to represent a principal. Once authenticated, a

Subject

is populated with associated identities, or

Principal

s. A

Subject

may have many

Principal

s. For example, a person may have a name

Principal

(John Doe) and a social security number

Principal

(123-45-6789), both of which help distinguish it from other

Subject

s. To retrieve the

Principal

s associated with a

Subject

, two methods are available:

     public Set getPrincipals();
     public Set getPrincipals(Class c);

The first method returns all

Principal

s contained in the

Subject

. The second method only returns those

Principal

s that are instances of

Class c

or

Class c

's subclasses. An empty set will return if the

Subject

has no associated

Principal

s. Note that the

java.security.acl.Group

interface is a subinterface of

java.security.Principal

, and so an instance in the

Principal

s set may represent a logical grouping of other principals or groups of principals.

Authentication classes

The following steps will authenticate a

Subject

:

  1. An application instantiates a LoginContext.
  2. The LoginContext consults a Configuration to load all the LoginModules configured for that application.
  3. The application invokes the LoginContext's login method.
  4. The login method invokes all the loaded LoginModules. Each LoginModule attempts to authenticate the Subject. Upon success, LoginModules associate relevant Principals and credentials with the Subject.
  5. The LoginContext returns the authentication status to the application.
  6. If authentication succeeds, the application retrieves the authenticated Subject from the LoginContext.

The

LoginContext

class provides the basic methods for authenticating

Subject

s and offers a way to develop an application independent of the underlying authentication technology. The

LoginContext

consults a

Configuration

to determine the authentication services -- or

LoginModule

s -- configured for a particular application. Therefore, you can plug in different

LoginModule

s under an application without changing the application itself. All

LoginContext

constructors share a common parameter:

name

. The

LoginContext

uses

name

to index the login

Configuration

. Actual authentication occurs with a call to the following method:

     public void login() throws LoginException;

When

login()

invokes, all the configured

LoginModule

s' respective login methods invoke to perform authentication. If authentication succeeds, the following method can retrieve the authenticated

Subject

(which may now hold

Principal

s, public credentials, and private credentials):

      public Subject getSubject();

To log out a

Subject

and remove its authenticated

Principal

s and credentials, use the method below:

     public void logout() throws LoginException;

The following code sample demonstrates the calls necessary to authenticate a

Subject

using the

LoginModule

s configured under the name

jwdomain

:

     // let the LoginContext instantiate a new Subject
     LoginContext lc = new LoginContext("jwdomain");
     try
     {
         // authenticate the Subject
         lc.login();
         System.out.println("authentication successful");
 
         // get the authenticated Subject
         Subject subject = lc.getSubject();
 
         ...
 
         // all finished -- logout
         lc.logout();
     }
     catch (LoginException le)
     {
         System.out.println("authentication unsuccessful");
         le.printStackTrace();
     }

With the

LoginModule

interface, developers can implement different authentication technologies that can be plugged under an application. For example, one

LoginModule

may perform username/password-based authentication, while others may interface to hardware devices such as smart card readers or biometric authenticators. To instantiate a

LoginModule

, a

LoginContext

expects each

LoginModule

to provide a public constructor that takes no arguments. Then, to initialize a

LoginModule

with the relevant information, a

LoginContext

calls the

LoginModule

's

initialize()

method. The

subject

argument is guaranteed to be nonnull. The signature of the

initialize()

method is:

    void initialize(Subject subject, CallbackHandler callbackHandler,
        Map sharedState, Map options);

The

login()

method starts authentication; its signature is:

      boolean login() throws LoginException;

An example method implementation might prompt the user for a username and password, and then verify the information against data stored in a naming service such as NIS or LDAP. Alternative implementations might interface to smart cards and biometric devices or simply extract user information from the underlying operating system. The validation of user identity by each

LoginModule

is considered Phase 1 of JAAS authentication. Authentication completes when the

LoginContext

calls:

      boolean commit() throws LoginException;

If Phase 1 succeeds, then the

commit()

method continues with Phase 2: associating relevant

Principal

s, public credentials, or private credentials with the

Subject

. If Phase 1 fails, then

boolean commit() throws LoginException;

removes any previously stored authentication state, such as usernames or passwords. The following method halts authentication:

     boolean abort() throws LoginException;

Typical implementations of that method also clean up previously stored authentication state. The following method logs out a

Subject

:

     boolean logout() throws LoginException;

That method removes the

Principal

s and credentials originally associated with the

Subject

during the commit operation. Credentials should be destroyed upon removal. When a

LoginModule

must communicate with the user to obtain authentication information, it uses a

CallbackHandler

. Applications implement the

CallbackHandler

interface and pass it to the

LoginContext

, which forwards it directly to the underlying

LoginModules

.

LoginModule

s use the

CallbackHandler

both to gather input from users (such as a password or smart-card PIN number) and to supply information to users (such as status information). By allowing the application to specify the

CallbackHandler

, underlying

LoginModule

s remain independent from the different ways applications interact with users. For example, a

CallbackHandler

's implementation for a GUI application might display a window to solicit user input. On the other hand, a

CallbackHandler

's implementation for a non-GUI environment, such as an application server, might simply obtain credential information using an application server API. The

CallbackHandler

interface has one method to implement:

      void handle(Callback[] callbacks)
        throws java.io.IOException, UnsupportedCallbackException;

The last authentication class I will cover is the

Callback

interface. It is a tagging interface that features several implementations, including

NameCallback

and

PasswordCallback

.

LoginModule

s use a

Callback

to request information required by the authentication mechanism the

LoginModule

encapsulates.

LoginModule

s pass an array of

Callback

s directly to the

CallbackHandler

's handle method during the authentication's login phase.

Inside the JBossSX JaasSecurityManager

Now let's return to the JBossSX security manager implementation. I'll start with an overview of how the JBoss security components interact. Figure 5 shows the main components and how the security domain assigned in the JBoss EJB and Web deployment descriptors ties them together.

Figure 5. Security component interaction overview Click on thumbnail to view full-size image.

Figure 5 depicts an enterprise application that contains both EJBs and Web content secured under the security domain

jwdomain

. The EJB and Web containers have a request interceptor architecture that includes a security interceptor, which enforces the container security model. At deployment time, the security domain in the

jboss.xml

and

jboss-web.xml

descriptors is used to obtain the security manager instance associated with the container and used by the security interceptor. When a secured component is requested, the security interceptor delegates security checks to the security manager instance associated with the container. For the JBossSX default security manager implementation, shown in Figure 5 as the

JaasSecurityMgr

component, security checks are based on the information associated with the

javax.security.auth.Subject

instance. That instance results from executing the JAAS login modules configured under the name matching the

security-domain

element value. We will drill into the

JaasSecurityManager

implementation and its use of JAAS in the following sections.

The JAAS in JaasSecurityManager

The default JBossSX security manager implementation

org.jboss.security.plugins.JaasSecurityManager

uses the JAAS packages to implement its behavior. In particular, its behavior derives from the login module (

javax.security.auth.spi.LoginModule

) whose configuration entry name matches the security domain to which the

JaasSecurityManager

has been assigned. The login module implements the security domain's principal authentication and role-mapping behavior. Hence, you can use the

JaasSecurityManager

across different security domains simply by plugging in different login module configurations for the domains.

The security check

Consider a client that invokes a method on an EJB configured to use a

JaasSecurityManager

instance for security. Figure 6 illustrates some components involved in the security check; the security check's key steps are outlined below the figure.

Figure 6. EJB access authentication procedure Click on thumbnail to view full-size image.
1 2 3 4 5 Page 2
Page 2 of 5