Use of JAAS Login Utility

| Feedback

# Use of JAAS Login Utility

The previous two tutorials, JAAS Authentication and JAAS Authorization, show how you can use the LoginContext and Subject classes to write a program to

- authenticate the user to verify his or her identity and

- associate an instance of a particular class representing the user (a Subject instance) with an access control context in such a way that subsequent security-sensitive operations will be allowed if the current policy grants the user the required permissions.

This tutorial describes a Login utility that performs the above operations and then executes any specified application as the authenticated user.

Use of the Login utility with a sample application is demonstrated in this tutorial. The next tutorial, a client/server application using the Java GSS-API, also uses the Login utility.

It is not necessary to read the previous two tutorials on JAAS authentication and authorization prior to reading this one. However, you may want to refer to some sections in those tutorials to obtain further details regarding certain topics, such as how to make user-based policy file statements. You should also read JAAS Login Configuration File for information as to what a login configuration file is, since one is needed for this and all other tutorials in this series.

As with all tutorials in this series of tutorials, the underlying technology used to support authentication is Kerberos. See Kerberos Requirements.

- What You Need to Know About the Login Utility

- Application and Other File Requirements

- The Sample Application Program

- The Login Configuration File

- The Policy File

- Running the Sample Program with the Login Utility

If you want to first see the tutorial code in action, you can skip directly to Running the Sample Program with the Login Utility and then go back to the other sections to learn more.

## What You Need to Know About the Login Utility

> You do not need to understand the code contained in Login.java; you can just use it as is. However, you need to understand some facts about what it does so that your program, policy file, and login configuration file will properly work with it. Below is a summary of these facts, followed by sections with further information and examples.

> The Login class does the following:

> - Assumes it is passed, as arguments, your application's top-level class name, followed by any arguments your application may require.

> - Assumes that the class name of your top-level application class is also used as the name of the entry to be looked up in your login configuration file.

> - Specifies the TextCallbackHandler class (from the `com.sun.security.auth.callback` package) as the class to be used when communicating with the user. This class can prompt the user for a user name and password.

> - Uses a LoginContext to authenticate the user. The LoginContext invokes the appropriate authentication technology, or LoginModule, to perform the authentication. LoginModules use a CallbackHandler (in our case, TextCallbackHandler) as needed to communicate with the user.

> - Allows the user three attempts to successfully log in.

> - Creates an instance of the MyAction class (also in `Login.java`), passing it the application arguments, if any.

> - Invokes `Subject.doAsPrivileged`, passing it a Subject representing the user, the MyAction instance, and a null AccessControlContext. The result is that the public static main method from your application is invoked and your application code is considered to be executed on behalf of the user.

## Application and Other File Requirements

> To utilize the Login utility to authenticate the user and execute your application, you may need a small number of additions or modifications to your login configuration file and policy file, as described in the following.

> - Application Requirements

> - Login Configuration File Requirements

> - Policy File Requirements

> ### Application Requirements

> > In order to utilize the Login utility, your application code does not need anything special. All you need is for the entry point of your application to be the `main` method of a class you write, as usual.

> > The way to invoke Login such that it will authenticate the user and then instantiate MyAction to invoke your application is the following:

> > >     java <options> Login <AppName> <app arguments>

> > where <AppName> is your application's top-level class name and <app arguments> are any arguments required by your application. See Running the Sample Program with the Login Utility for the full command used for this tutorial.

> ### Login Configuration File Requirements

> > Whenever a LoginContext is used to authenticate the user, you need a login configuration file to specify the desired login module. See the The Login Configuration File section in the JAAS authentication tutorial for more information as to what a login configuration file is and what it contains.

> > When you use the Login utility, the name for the login configuration file entry must be exactly the same as your top-level application class name. See The Login Configuration File in this tutorial for an example.

> ### Policy File Requirements

> > Whenever you run an application with a security manager, you need a policy indicating the permissions granted to specific code, or to specific code being executed by a specific user (or users). One way of specifying the policy is by `grant` statements in a policy file. See The Policy File for more information.

> > If you use the Login utility to invoke your application, then you will need to grant it various permissions, as described in Permissions Required by the Login and MyAction Classes.

## The Sample Application Program

> The Sample.java application used for this tutorial performs the same actions as the `SampleAction.java` application did in the previous (JAAS Authorization) tutorial. It does the following:
> - Reads and prints the value of the `java.home` system property,

> - Reads and prints the value of the `user.home` system property, and

> - Determines whether or not a file named `foo.txt` exists in the current directory.

> Here is the code:

> >     import java.io.File;

> >     public class Sample {

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

> >         // If there were any arguments to read, we'd do it here.

> >         System.out.println("\nYour java.home property value is: "
> >                     +System.getProperty("java.home"));

> >         System.out.println("\nYour user.home property value is: "
> >                     +System.getProperty("user.home"));

> >         File f = new File("foo.txt");
> >         System.out.print("\nfoo.txt does ");
> >         if (!f.exists())
> >             System.out.print("not ");
> >         System.out.println("exist in the current working directory.");
> >       }
> >     }

## The Login Configuration File

> The sample.conf login configuration file for this tutorial contains a single entry, just like the login configuration file for the previous (JAAS Authorization) tutorial. The entry contents are the same since the class implementing the desired authentication technology in both cases is the Krb5LoginModule in the `com.sun.security.auth.module` package.

> The only difference is the name used for the entry. In the previous tutorial we used the name "JaasSample", since that is the name used by the JaasAzn class to look up the entry. When you use the Login utility with your application, it expects the name for your login configuration file entry to be the same as the name of your top-level application class. That application class for this tutorial is named "Sample" so that must also be the name of the login configuration file entry. Thus the login configuration file looks like the following:

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

> The "required" indicates that login using the 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.

## The Policy File

> The Login, MyAction, and Sample classes all perform some security-sensitive operations and thus relevant permissions are required in a policy file in order for the operations to be executed.

> ### Permissions Required by the Login and MyAction Classes

> > For this tutorial, you will create a `Login.jar` JAR file containing the `Login.class` and `MyAction.class` files. You need to grant `Login.jar` various permissions, specifically the ones required for invoking the security-sensitive methods the `Login.jar` classes call, as well as all the permissions required by your application. Otherwise, access control checks will fail.

> > The simplest thing to do, and what we recommend, is to grant `Login.jar AllPermission`. For this tutorial, the `Login.jar` file is assumed to be in the current directory and the policy file includes the following:

> > >     grant codebase "file:./Login.jar" {
> > >        permission java.security.AllPermission;
> > >     };

> ### Permissions Required by Sample

> > (Note: This section is essentially a modified copy of the Permissions Required by SampleAction section from the previous (JAAS Authorization) tutorial, since Sample and SampleAction perform the same operations and thus require the same permissions.)

> > The `Sample` code does three operations for which permissions are required. It

> > - reads the value of the "java.home" system property.

> > - reads the value of the "user.home" system property.

> > - checks to see whether or not a file named `foo.txt` exists in the current directory.

> > The permissions required for these operations are the following:

> > >     permission java.util.PropertyPermission "java.home", "read";
> > >     permission java.util.PropertyPermission "user.home", "read";
> > >     permission java.io.FilePermission "foo.txt", "read";

> > We need to grant these permissions to the code in `Sample.class`, which we will place in a JAR file named `Sample.jar`. However, our `grant` statement will grant the permissions not just to the code but to a specific authenticated user executing the code. This illustrates how you can use a Principal designation in a `grant` statement to restrict execution of security-sensitive operations in code to a specific user rather than allowing the permissions to all users executing the code.

> > Thus, as explained in How Do You Make Principal-Based Policy File Statements?, our `grant` statement looks like the following:

> > >     grant codebase "file:./Sample.jar",
> > >         Principal javax.security.auth.kerberos.KerberosPrincipal
> > >             "your_user_name@your_realm"  {

> > >        permission java.util.PropertyPermission "java.home", "read";
> > >        permission java.util.PropertyPermission "user.home", "read";
> > >        permission java.io.FilePermission "foo.txt", "read";
> > >     };

> > Important: You must substitute your Kerberos user name (complete with "@" and realm) for "`your_user_name@your_realm`". For example, if your user name is "mjones" and your realm is "KRBNT-OPERATIONS.ABC.COM", you would use "mjones@KRBNT-OPERATIONS.ABC.COM" (complete with the quotes).

> ### The Full Policy File

> > The full policy file is sample.policy.

## Running the Sample Program with the Login Utility

> To execute the Sample application with the Login utility, do the following:

> 1. Place the following files into a directory:

>    - The Login.java source file.
>    - The Sample.java source file.
>    - The sample.conf login configuration file.
>    - The sample.policy policy file.

> 2. Replace "your_user_name@your_realm" in `sample.policy` with your user name and realm.

> 3. Compile `Login.java` and `Sample.java`:

>    >     javac Login.java Sample.java

>    Note that `Login.java` contains two classes and thus compiling `Login.java` creates `Login.class` and `MyAction.class`.

> 4. Create a JAR file named `Login.jar` containing `Login.class and MyAction.class`:

>    >     jar -cvf Login.jar Login.class MyAction.class

> 5. Create a JAR file named `Sample.jar` containing `Sample.class`:

>    >     jar -cvf Sample.jar Sample.class

> 6. Execute the `Login` class, specifying

>    - by an appropriate `-classpath` clause that classes should be searched for in the `Login.jar` and `Sample.jar` JAR files,

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

>    - by `-Djava.security.krb5.realm=<your_realm>` that your Kerberos realm is the one specified.

>    - by `-Djava.security.krb5.kdc=<your_kdc>` that your Kerberos KDC is the one specified.

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

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

>    You pass the name of your application (in this case, "Sample") as an argument to Login. You would then add as arguments any arguments required by your application, but in our case Sample does not require any.

>    Below are the full commands to use for both Microsoft Windows and Unix systems. The only difference is that on Windows systems you use semicolons to separate classpath items, while you use colons for that purpose on Unix systems. Be sure to replace `<your_realm>` with your Kerberos realm, and `<your_kdc>` with your Kerberos KDC.

>    Here is the full command for Windows systems:

>    >     java -classpath Login.jar;Sample.jar
>    >      -Djava.security.manager
>    >      -Djava.security.krb5.realm=<your_realm>
>    >      -Djava.security.krb5.kdc=<your_kdc>
>    >      -Djava.security.policy=sample.policy
>    >      -Djava.security.auth.login.config=sample.conf Login Sample

>    Here is the full command for UNIX systems:

>    >     java -classpath Login.jar:Sample.jar
>    >      -Djava.security.manager
>    >      -Djava.security.krb5.realm=<your_realm>
>    >      -Djava.security.krb5.kdc=<your_kdc>
>    >      -Djava.security.policy=sample.policy
>    >      -Djava.security.auth.login.config=sample.conf Login Sample

>    Type the full command 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.

>    You will be prompted for your Kerberos user name and password, and the underlying Kerberos login module specified in the login configuration file will log you into Kerberos. Once authentication is successfully completed, the `Sample` code will be executed on behalf of you, the user. The `sample.policy` policy file grants you the required permissions, so you will see a display of the values of your `java.home` and `user.home` system properties and a statement as to whether or not you have a file named `foo.txt` in the current directory.

>    For login troubleshooting suggestions, see Troubleshooting.

| Feedback