JAAS Authentication

| Feedback

# JAAS Authentication

> The JavaTM Authentication and Authorization Service (JAAS) was introduced as an optional package to the JavaTM 2 SDK, Standard Edition (J2SDK), v 1.3. JAAS has now been integrated into the J2SDK, v 1.4.

> JAAS can be used for two purposes:

> - for authentication of users, to reliably and securely determine who is currently executing Java code, regardless of whether the code is running as an application, an applet, a bean, or a servlet; and

> - for authorization of users to ensure they have the access control rights (permissions) required to do the actions performed.

> This section provides a basic tutorial for the authentication component. The authorization component will be described in the JAAS Authorization tutorial.

> JAAS authentication is performed in a pluggable fashion. This permits Java applications to remain independent from underlying authentication technologies. New or updated technologies can be plugged in without requiring modifications to the application itself. An implementation for a particular authentication technology to be used is determined at runtime. The implementation is specified in a login configuration file. The authentication technology used for this tutorial is Kerberos. (See Kerberos Requirements.)

> The rest of this tutorial consists of the following sections:

> 1. The Authentication Tutorial Code

> 2. The Login Configuration

> 3. Running the Code

> 4. Running the Code with a Security Manager

> If you want to first see the tutorial code in action, you can skip directly to Running the Code and then go back to the other sections to learn about coding and configuration file details.

> ## The Authentication Tutorial Code

> > Our authentication tutorial code is contained in a single source file, JaasAcn.java. This file's `main` method performs the authentication and then reports whether or not authentication succeeded.

> > The code for authenticating the user is very simple, consisting of just two steps:

> > 1. Instantiate a LoginContext.

> > 2. Call the LoginContext's `login` method.

> > First the basic code is shown, followed by a complete listing of the `JaasAcn.java` source file, complete with import statements and error handling.

> > ### Instantiating a LoginContext

> > > In order to authenticate a user, you first need a `javax.security.auth.login.LoginContext`. Here is the basic way to instantiate a LoginContext:

> > > >     import javax.security.auth.login.*;
> > > >     . . .
> > > >     LoginContext lc =
> > > >         new LoginContext(<config file entry name>,
> > > >                <CallbackHandler to be used for user interaction>);

> > > and here is the specific way our tutorial code does the instantiation:

> > > >     import javax.security.auth.login.*;
> > > >     import com.sun.security.auth.callback.TextCallbackHandler;
> > > >     . . .
> > > >     LoginContext lc =
> > > >         new LoginContext("JaasSample",
> > > >               new TextCallbackHandler());

> > > The arguments are the following:

> > > 1. The name of an entry in the JAAS login configuration file

> > >    This is the name for the LoginContext to use to look up an entry for this application in the JAAS login configuration file, described here. Such an entry specifies the class(es) that implement the desired underlying authentication technology(ies). The class(es) must implement the LoginModule interface, which is in the `javax.security.auth.spi` package.

> > >    In our sample code, we use the `Krb5LoginModule` in the `com.sun.security.auth.module` package, which performs Kerberos authentication.

> > >    The entry in the login configuration file we use for this tutorial (see jaas.conf) has the name "JaasSample", so that is the name we specify as the first argument to the LoginContext constructor.

> > > 2. A CallbackHandler instance.

> > >    When a LoginModule needs to communicate with the user, for example to ask for a user name and password, it does not do so directly. That is because there are various ways of communicating with a user, and it is desirable for LoginModules to remain independent of the different types of user interaction. Rather, the LoginModule invokes a CallbackHandler to perform the user interaction and obtain the requested information, such as the user name and password. (CallbackHandler is an interface in the `javax.security.auth.callback` pkg.)

> > >    An instance of the particular CallbackHandler to be used is specified as the second argument to the LoginContext constructor. The LoginContext forwards that instance to the underlying LoginModule (in our case Krb5LoginModule). An application typically provides its own CallbackHandler implementation. Two simple CallbackHandlers, TextCallbackHandler and DialogCallbackHandler, are provided in the `com.sun.security.auth.callback` package as sample implementations. Our code uses the TextCallbackHandler, which outputs information to and reads input from the command line.

> > ### Calling the LoginContext's `login` Method

> > > Once we have a LoginContext `lc`, we can call its `login` method to carry out the authentication process:

> > > >     lc.login();

> > > The LoginContext instantiates a new empty `javax.security.auth.Subject` object (which represents the user or service being authenticated). The LoginContext constructs the configured LoginModule (in our case Krb5LoginModule) and initializes it with this new Subject and TextCallbackHandler.

> > > The LoginContext's `login` method then calls methods in the Krb5LoginModule to perform the login and authentication. The Krb5LoginModule will utilize the TextCallbackHandler to obtain the user name and password. Then the Krb5LoginModule will use this information to get the user credentials from the Kerberos KDC. See the Kerberos reference documentation.

> > > If authentication is successful, the Krb5LoginModule populates the Subject with (1) a Kerberos Principal representing the user and (2) the user's credentials (TGT). See Subjects, Principals, Authentication, and Credentials for information on these terms.

> > > The calling application can subsequently retrieve the authenticated Subject by calling the LoginContext's `getSubject` method, although doing so is not necessary for this tutorial.

> > ### The Complete `JaasAcn.java` Code

> > > Now that you have seen the basic code required to authenticate the user, we can put it all together into the full class in JaasAcn.java, which includes relevant import statements and error handling:

> > > >     import javax.security.auth.*;
> > > >     import javax.security.auth.callback.*;
> > > >     import javax.security.auth.login.*;
> > > >     import com.sun.security.auth.callback.TextCallbackHandler;

> > > >     /**
> > > >      * This JaasAcn application attempts to authenticate a user
> > > >      * and reports whether or not the authentication was successful.
> > > >      */
> > > >     public class JaasAcn {

> > > >       public static void main(String[] args) {

> > > >           // Obtain a LoginContext, needed for authentication. Tell
> > > >           // it to use the LoginModule implementation specified by
> > > >           // the entry named "JaasSample" in the JAAS login
> > > >           // configuration file and to also use the specified
> > > >           // CallbackHandler.
> > > >           LoginContext lc = null;
> > > >           try {
> > > >               lc = new LoginContext("JaasSample",
> > > >                           new TextCallbackHandler());
> > > >           } catch (LoginException le) {
> > > >               System.err.println("Cannot create LoginContext. "
> > > >                   + le.getMessage());
> > > >               System.exit(-1);
> > > >           } catch (SecurityException se) {
> > > >               System.err.println("Cannot create LoginContext. "
> > > >                   + se.getMessage());
> > > >               System.exit(-1);
> > > >           }

> > > >           try {

> > > >               // attempt authentication
> > > >               lc.login();

> > > >           } catch (LoginException le) {

> > > >               System.err.println("Authentication failed: "
> > > >               System.err.println("  " + le.getMessage());
> > > >               System.exit(-1);

> > > >           }

> > > >           System.out.println("Authentication succeeded!");

> > > >         }
> > > >     }

> ## The Login Configuration

> > JAAS authentication is performed in a pluggable fashion, so applications can remain independent from underlying authentication technologies. A system administrator determines the authentication technologies, or LoginModules, to be used for each application and configures them in a login Configuration. The source of the configuration information (for example, a file or a database) is up to the current javax.security.auth.login.Configuration implementation. The default `Configuration` implementation from Sun Microsystems reads configuration information from configuration files, as described in com.sun.security.auth.login.ConfigFile.html.

> > See JAAS Login Configuration File for information as to what a login configuration file is, what it contains, and how to specify which login configuration file should be used.

> > ### The Login Configuration File for This Tutorial

> > > As noted, the login configuration file we use for this tutorial, jaas.conf, contains just one entry, which is

> > > >     JaasSample {
> > > >       com.sun.security.auth.module.Krb5LoginModule required;
> > > >     };

> > > This entry is named "JaasSample" and that is the name that our tutorial application, `JaasAcn`, uses to refer to this entry. The entry specifies that the LoginModule to be used to do the user authentication is the Krb5LoginModule in the `com.sun.security.auth.module` package and that this Krb5LoginModule is required to "succeed" in order for authentication to be considered successful. The Krb5LoginModule succeeds only if the name and password supplied by the user are successfully used to log the user into the Kerberos KDC.

> > > For information about all the possible options that can be passed to Krb5LoginModule, see the Krb5LoginModule documentation.

> ## Running the Code

> > To execute our JAAS authentication tutorial code, all you have to do is

> > 1. Place the JaasAcn.java application source file and the jaas.conf login configuration file into a directory.

> > 2. Compile `JaasAcn.java`:

> >    >     javac JaasAcn.java

> > 3. Execute the `JaasAcn` application, specifying

> >    - by `-Djava.security.krb5.realm=<your_realm>` that your Kerberos realm is the one specified. For example, if your realm is "KRBNT-OPERATIONS.ABC.COM" you'd put `-Djava.security.krb5.realm=KRBNT-OPERATIONS.ABC.COM`.

> >    - by `-Djava.security.krb5.kdc=<your_kdc>` that your Kerberos KDC is the one specified. For example, if your KDC is "samplekdc.abc.com" you'd put `-Djava.security.krb5.kdc=samplekdc.abc.com`.

> >    - by `-Djava.security.auth.login.config=jaas.conf` that the login configuration file to be used is `jaas.conf`.

> > The full command is below. Be sure to replace `<your_realm>` with your Kerberos realm, and `<your_kdc>` with your Kerberos KDC.

> > >     java -Djava.security.krb5.realm=<your_realm>
> > >      -Djava.security.krb5.kdc=<your_kdc>
> > >      -Djava.security.auth.login.config=jaas.conf JaasAcn

> > Type all that on one line. Multiple lines are used here for legibility.

> > You will be prompted for your Kerberos user name and password, and the underlying Kerberos authentication mechanism specified in the login configuration file will log you into Kerberos. If your login is successful, you will see the following message:

> > >     Authentication succeeded!

> > If the login is not successful (for example, if you misspell your password), you will see

> > >     Authentication failed:

> > followed by a reason for the failure. For example, if you mistype your user name, you may see a message like the following (where the formatting is slightly modified here to increase legibility):

> > >     Authentication failed:
> > >       Kerberos Authentication Failed:
> > >         javax.security.auth.login.LoginException:
> > >           KrbException: Client not found in Kerberos database

> > For login troubleshooting suggestions, see Troubleshooting.

> > After fixing any problems, re-run the program to try again.

> ## Running the Code with a Security Manager

> > When a Java program is run with a security manager installed, the program is not allowed to access resources or otherwise perform security-sensitive operations unless it is explicitly granted permission to do so by the security policy in effect. In Java platforms that are compatible with J2SE v 1.2 and later, the permission must be granted by an entry in a policy file.

> > Most browsers install a security manager, so applets typically run under the scrutiny of a security manager. Applications, on the other hand, do not, since a security manager is not automatically installed when an application is running. Thus an application, like our `JaasAcn` application, by default has full access to resources.

> > To run an application with a security manager, simply invoke the interpreter with a `-Djava.security.manager` argument included on the command line.

> > If you try invoking `JaasAcn` with a security manager but without specifying any policy file, you will get the following (unless you have a default policy setup elsewhere that grants the required permissions or grants `AllPermission`):

> >     % java -Djava.security.manager \
> >      -Djava.security.krb5.realm=<your_realm> \
> >      -Djava.security.krb5.kdc=<your_kdc> \
> >      -Djava.security.auth.login.config=jaas.conf JaasAcn
> >     Exception in thread "main" java.security.AccessControlException:
> >       access denied (
> >       javax.security.auth.AuthPermission createLoginContext.JaasSample)

> > As you can see, you get an AccessControlException, because we haven't created and used a policy file granting our code the permission that is required in order to be allowed to create a LoginContext.

> > Here are the complete steps required in order to be able to run our `JaasAcn` application with a security manager installed. You can skip the first two steps if you have already done them, as described in Running the Code.

> > 1. Place the JaasAcn.java application source file and the jaas.conf login configuration file into a directory.

> > 2. Compile `JaasAcn.java`:

> >    >     javac JaasAcn.java

> > 3. Create a JAR file containing `JaasAcn.class`:

> >    >     jar -cvf JaasAcn.jar JaasAcn.class

> >    This command creates a JAR file, `JaasAcn.jar`, and places the `JaasAcn.class` file inside it.

> > 4. Create a policy file granting the code in the JAR file the required permission.

> >    The permission that is needed by code attempting to instantiate a LoginContext is a `javax.security.auth.AuthPermission` with target "createLoginContext.<entry name>". Here, <entry name> refers to the name of the login configuration file entry that the application references in its instantiation of LoginContext. The name used by our `JaasAcn` application's LoginContext instantiation is "JaasSample", as you can see in the code:

> >    >     LoginContext lc =
> >    >         new LoginContext("JaasSample",
> >    >               new TextCallbackHandler());

> >    Thus, the permission that needs to be granted to `JaasAcn.jar` is

> >    >     permission javax.security.auth.AuthPermission
> >    >       "createLoginContext.JaasSample";

> >    Copy the policy file jaasacn.policy to the same directory as that in which you stored `JaasAcn.java`, etc. This is a text file containing the following `grant` statement to grant `JaasAcn.jar` (in the current directory) the required permission:

> >    >     grant codebase "file:./JaasAcn.jar" {
> >    >        permission javax.security.auth.AuthPermission
> >    >                         "createLoginContext.JaasSample";
> >    >     };

> >    Note: Policy files and the structure of entries within them are described in Default Policy Implementation and Policy File Syntax. Permissions are described here.

> > 5. Execute the `JaasAcn` application, specifying

> >    1. by an appropriate `-classpath` clause that classes should be searched for in the `JaasAcn.jar` JAR file,

> >    2. by `-Djava.security.manager` that a security manager should be installed,

> >    3. by `-Djava.security.krb5.realm=<your_realm>` that your Kerberos realm is the one specified. For example, if your realm is "KRBNT-OPERATIONS.ABC.COM" you'd put `-Djava.security.krb5.realm=KRBNT-OPERATIONS.ABC.COM`.

> >    4. by `-Djava.security.krb5.kdc=<your_kdc>` that your Kerberos KDC is the one specified. For example, if your KDC is "samplekdc.abc.com" you'd put `-Djava.security.krb5.kdc=samplekdc.abc.com`.

> >    5. by `-Djava.security.policy=jaasacn.policy` that the policy file to be used is `jaasacn.policy`, and

> >    6. by `-Djava.security.auth.login.config=jaas.conf` that the login configuration file to be used is `jaas.conf`.

> >    The full command is below. Be sure to replace `<your_realm>` with your Kerberos realm, and `<your_kdc>` with your Kerberos KDC.

> >        java -classpath JaasAcn.jar -Djava.security.manager
> >         -Djava.security.krb5.realm=<your_realm>
> >         -Djava.security.krb5.kdc=<your_kdc>
> >         -Djava.security.policy=jaasacn.policy
> >         -Djava.security.auth.login.config=jaas.conf JaasAcn

> >    Type all that on one line. Multiple lines are used here for legibility. If the command is too long for your system, you may need to place it in a .bat file (for Windows) or a .sh file (for UNIX) and then run that file to execute the command.

> >    Since the specified policy file contains an entry granting the code the required permission, `JaasAcn` will be allowed to instantiate a LoginContext and continue execution. You will be prompted for your Kerberos user name and password, and the underlying Kerberos authentication mechanism specified in the login configuration file will log you into Kerberos. If your login is successful, you will see the message "Authentication succeeded!" and if not, you will see "Authentication failed:" followed by a reason for the failure.

> >    For login troubleshooting suggestions, see Troubleshooting.

| Feedback