Return-Path: <env_623340616925952587@hermes.java.sun.com>
Received: from fort-point-station.mit.edu by po10.mit.edu (8.9.2/4.7) id AAA05899; Sat, 28 Jul 2001 00:16:11 -0400 (EDT)
Received: from hermes.java.sun.com (hermes.java.sun.com [204.160.241.85])
	by fort-point-station.mit.edu (8.9.2/8.9.2) with SMTP id AAA27947
	for <alexp@mit.edu>; Sat, 28 Jul 2001 00:16:10 -0400 (EDT)
Message-Id: <200107280416.AAA27947@fort-point-station.mit.edu>
Date: Fri, 27 Jul 2001 21:16:10 PDT
From: "JDC Tech Tips" <body_623340616925952587@hermes.java.sun.com>
To: alexp@mit.edu
Subject: JDC Tech Tips  July 27, 2001
Precedence: junk
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
X-Mailer: Beyond Email 2.2

 J  D  C    T  E  C  H    T  I  P  S

                      TIPS, TECHNIQUES, AND SAMPLE CODE


WELCOME to the Java Developer Connection(sm) (JDC) Tech Tips, 
July 27, 2001. This issue covers the Java(tm) Authentication and
Authorization Service (JAAS). It introduces some key concepts in 
JAAS and shows you how to make use of these concepts. The tips
are: 

         * Introduction to JAAS
         * Using JAAS

In order to run the code in this tip you will need access
to JAAS version 1.0, which is available at:

  http://java.sun.com/products/jaas         
                 
These tips were developed using Java 2 SDK, Standard Edition, 
v 1.3.

This issue of the JDC Tech Tips is written by Stuart Halloway,
a Java specialist at DevelopMentor (http://www.develop.com/java).

You can view this issue of the Tech Tips on the Web at
http://java.sun.com/jdc/JDCTechTips/2001/tt0727.html

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
INTRODUCTION TO JAAS

The Java Authentication and Authorization Service (JAAS) extends 
the Java security model to perform checks based on the identity 
of the caller. Before you use JAAS, you need to understand some 
key concepts. These are:

o Subject
o Principal
o Client and LoginContext
o Configuration File
o Provider 
o Java Policy File 
o JAAS Policy File


Subject 

In JAAS, a subject is some identity in a system that you want to
authenticate and to which you want to assign permissions. For
example, a subject can be a human user, a machine, or a process.
Subjects are represented by the javax.security.auth.Subject class.


Principal

Just as in the real world, a Subject can have relationships with
several different authorities. For example, you might have one 
password and set of privileges at your bank, and a different 
password and set for of privileges for your voice mail. In this
example, the authorities are the bank and the voice mail system.
In JAAS, a subject's multiple interactions with authorities are 
are represented by classes that implement the 
java.security.Principal interface. So a Principal is a class
that represents a Subject's interactions with an authority.
A Principal simply knows its name and provides sensible overrides 
for the Object methods, as the following SimplePrincipal class 
demonstrates.

Note: You'll use this class and other components in an 
application that uses JAAS. Don't try to compile and use this 
class individually. Instructions for building and running
the application are in the tip that follows this one, titled
"Using JAAS."

import java.security.Principal;

public final class SimplePrincipal implements Principal {
    private final String name;

    public SimplePrincipal(String name) {
        if (name == null) {
            throw new IllegalArgumentException(
                                     "Name cannot be null");
        }
        this.name = name;
    }
    public int hashCode() {
        return name.hashCode();
    }    
    public java.lang.String getName() {
        return name;
    }
    public java.lang.String toString() {
        return "SimplePrincipal: " + name;
    }
    public boolean equals(java.lang.Object obj) {
        if (obj == null) return false;
        if (!(obj instanceof SimplePrincipal)) return false;
        SimplePrincipal other = (SimplePrincipal) obj;
        return name.equals(other.getName());
    }
}


Client and LoginContext

In order to associate a Principal with a Subject, clients must
login. JAAS provides a concrete class, LoginContext, that acts as
a session with a group of one or more authentication providers. 
The following JAASClient class demonstrates using a LoginContext:

import java.util.Iterator;
import java.security.PrivilegedAction;
import javax.security.auth.Subject;
import javax.security.auth.login.LoginContext;

public class JAASClient {
  public static void main(String [] args) {
    try {
      loginAndDoSomething();
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }
  public static void loginAndDoSomething() throws Exception {
    LoginContext ctx = new LoginContext("SimpleLogin");
    ctx.login();
    Subject subj = ctx.getSubject();
    System.out.println("Login assigned these principals: ");
    Iterator it = subj.getPrincipals().iterator(); 
    while (it.hasNext()) 
        System.out.println("\t" + it.next());
    
    Subject.doAs(subj, new PrivilegedAction() {
        public Object run() {
          System.out.println("You live at " + 
                           System.getProperty("user.home"));
          return null;
        }
      });
    ctx.logout();
  }
}

The LoginContext constructor prepares to authenticate based on a
named configuration. In this case, the configuration is named
SimpleLogin (more on this in a moment). The call to login then
causes the LoginContext to call one or more authentication
providers. The call to getSubject returns a Subject that contains
any Principals that the authenticators chose to assign. The doAs
method then attempts a secured operation, which will succeed if
one of the Principals has the appropriate Permission.

The call to getPrincipals is for debugging; it prints the
Principals that login assigned to the Subject.


Configuration File

The LoginContext finds the named configuration from a 
configuration file that looks like this:

//File conf/simple.conf
SimpleLogin {
   SimpleLoginModule required;
};

This file tells the LoginContext to load a class named
SimpleLoginModule, which is a service provider for some
authentication strategy. The "required" means that this class's
approval is necessary for login to succeed. The LoginContext
allows multiple authentication providers to be used in tandem, in
which case, additional entries would appear inside the 
SimpleLogin block.


Provider

A JAAS authentication provider provides the authentication
strategy. In JAAS, an authentication strategy is implemented 
through the LoginModule interface. So the SimpleLoginModule must 
implement the LoginModule interface:

package java.security.auth.spi;
public interface LoginModule {
  boolean abort();
  boolean commit();
  void initialize(Subject s, CallbackHandler ch, 
                  Map shared, Map options);
  boolean login();
  boolean logout();
}

The LoginContext will call these methods in the following
sequence:

1. initialize gives the service provider a Subject, to which it 
   can later attach Principals to if login succeeds. The
   CallbackHandler is a client-provided set of interfaces for
   entering authentication information. These interfaces decouple
   the service provider from the particular input devices being 
   used, such as a computer keyboard or cell phone. The shared 
   map contains general configuration information, and the 
   options map contains a provider-specific configuration.
   
2. login tells the provider to authenticate the Subject. 
   Principals are not assigned at this time.
   
3. commit tells the provider that the LoginContext accepts the 
   results from all the other providers, and so the provider can
   assign Principals.
   
4. abort tells the provider that even though it may have
   authenticated the Subject, some other Provider failed and the
   overall login should fail. The provider forgets that it ever
   saw the login succeed and does not assign Principals to the
   Subject.
   
5. logout cancels the assignment of Principals to the Subject.

Now let's look at the content of SimpleLoginModule. In this 
example, it provides a rudimentary implementation of LoginModule 
that tests the user's knowledge of movie trivia:

import java.io.*;
import java.util.*;
import java.security.Principal;
import javax.security.auth.Subject;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.spi.LoginModule;

public class SimpleLoginModule implements LoginModule {
  private static final int NOT_AUTHENTICATED = 0;
  private static final int AUTHENTICATED = 1;
  private static final int AUTHENTICATE_COMMITTED = 2;

  private int state;
  private SimplePrincipal sp;
  private Subject sub;

  public boolean abort() {
    if ((sub != null) && (sp  != null)) {
      Set prins = sub.getPrincipals();
      if (prins.contains(sp)) {
        prins.remove(sp);
      }
    }
    sub = null;
    sp = null;
    state = NOT_AUTHENTICATED;
    return true;
  }
  public boolean commit() {
    if (state < AUTHENTICATED) {
      return false;
    }
    if (sub == null) {
      return false;
    }
    Set prins = sub.getPrincipals();
    if (!prins.contains(sp)) {
      prins.add(sp);
    }
    state = AUTHENTICATE_COMMITTED;
    return true;
  }
  public void initialize(Subject s, CallbackHandler ch, 
                  Map shared, Map options) {
    state = NOT_AUTHENTICATED;
    sp = null;
    sub = s;
  }
  public boolean login() {
    BufferedReader br = new BufferedReader(
                        new InputStreamReader(System.in));
    System.err.println("What can Jack Burton see? ");
    try {
      String resp = br.readLine();
      if (!resp.equalsIgnoreCase("things no one else can see")) {
        return false;
      }
    }
    catch (IOException ioe) {
      return false;
    }
    sp = new SimplePrincipal("Jack");
    state = AUTHENTICATED;
    return true;
  }
  public boolean logout() {
    state = NOT_AUTHENTICATED;
    sp = null;
    sub = null;
    return true;
  }
}

The SimpleLogin module is indeed very simple, recognizing only 
one Principal ("Jack") and only one authentication string, both 
of which are hard-coded.


Java Policy File 

A JAAS authentication provider is a highly-trusted part of the
system, and needs special permissions. To grant these 
permissions, you will need to specify a Java 2 policy file like 
this one:

//file conf/JAASProvider.policy
//trust the provider
grant codeBase "file:./provider/" {
  permission java.security.AllPermission;
};

//trust JAAS
grant codeBase "file:/java/jaas1_0/lib/jaas.jar" {
  permission java.security.AllPermission;
};

//these permissions are needed by the client
grant codeBase "file:./client/" {
  permission javax.security.auth.AuthPermission "createLoginContext";
  permission javax.security.auth.AuthPermission "doAs";
  permission java.util.PropertyPermission "user.home", "read";
};

Make sure to edit the jaas.jar codeBase entry to point to the
location of jaas.jar on your local system. The other URLs are
relative and do not need to be edited.

The provider files and the the JAAS API files are completely
trusted. The client code has the permissions it needs to 
bootstrap a LoginContext and to perform an authentication check. 
The client can also read the "user.home" property, which is the 
"sensitive operation" being demonstrated in this example.


JAAS Policy File

JAAS defines a policy file format for assigning permissions to
authenticated clients. The format looks very similar to the 
normal Java 2 policy file. In fact, Java 2 SDK version 1.4 will 
support both formats from a single file. For JAAS 1.0, the 
JAAS-specific sections are in a separate file that looks like 
this:

//file conf/SimpleJAAS.policy
grant Principal SimplePrincipal "Jack" {
   permission java.util.PropertyPermission "user.home", "read";
};

The permission settings look exactly like Java 2 security 
permission settings. The only difference is in the grant 
declaration, which can list a Principal instead of, or in 
addition to, the normal codeBase and signedBy settings. This 
simple example gives Jack permission to read the user.home 
property. 

In the 1.4 version of the Java 2 SDK, a separate JAAS policy 
file will not be necessary. All settings will be controlled by 
the standard policy.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
USING JAAS

Let's build and run a JAAS application using the components
described in the "Introduction to JAAS," above. All you need to 
do is start the client in a virtual machine with the correct 
configuration. Specifically, you:

o Compile the Java classes. Remember to first ensure that
  your class path includes the jaas.jar file. Compile the client 
  class (JAASClient) to a subdirectory named "client." Compile 
  all the other classes to a subdirectory named "provider."
  
o Place the configuration file (simple.conf) in a subdirectory
  named "conf."  
  
o Place the policy files (JAASProvider.policy and 
  SimpleJAAS.policy) in the "conf" subdirectory.  

With those files in place, issue the following command. Make sure
to edit the command to specify the correct location of jaas.jar.

On Windows systems (this is shown in multiple lines for
readibility. You should enter the command as a single line): 

  java -cp client;provider;d:\java\jaas1_0\lib\jaas.jar
       -Djava.security.manager 
       -Djava.security.policy=conf/JAASProvider.policy 
       -Djava.security.auth.policy=conf/SimpleJAAS.policy  
       -Djava.security.auth.login.config=conf/simple.conf JAASClient
       
On UNIX systems: 

  java -cp client:provider:/java/jaas1_0/lib/jaas.jar \
       -Djava.security.manager \
       -Djava.security.policy=conf/JAASProvider.policy \
       -Djava.security.auth.policy=conf/SimpleJAAS.policy \ 
       -Djava.security.auth.login.config=conf/simple.conf JAASClient       

If you examine the command, you'll see that it: 
   
o Turns on Java 2 security 
  (-Djava.security.manager)
   
o Gives the provider the Java 2 permissions it needs 
  (-Djava.security.policy=JAASProvider.policy)
   
o Gives the client the JAAS permissions it needs
  (-Djava.security.auth.policy=SimpleJAAS.policy
   
o Tells the LoginContext where to find the configuration file
  (-Djava.security.auth.login.config=simple.conf)

You should see a session like the following (assuming you enter 
the correct answer to the question):

  What can Jack Burton see? 
  things no one else can see
  Login assigned these principals: 
        SimplePrincipal: Jack 
  You live at {your home directory}

In general, you do not need to write your own providers or
Principals. Instead, you can use a standard provider and 
Principals that integrate with your OS login, smart card, or 
other authentication provider. Otherwise, what you do to build 
and run an application that uses JAAS is very similar to what 
was shown above. Specifically, you need to:
 
o Create a LoginContext that refers to a named JAAS policy entry.
o Configure your provider in the Java 2 security policy.
o Configure your JAAS policy.
o Use Subject.doAs to control sensitive operations.

The example code shown above is quite simple. Here are some
other experiments you could try:

o A real authentication provider should not use System.in and
  System.err. The CallbackHandler interface is provided for this
  purpose. Rewrite the SimpleLoginModule to use a 
  CallbackHandler provided by the client.

o Providers do not actually need AllPermission. To discover the
  permissions that are really needed, remove the AllPermission
  entries from the JAASProvider.policy file. Then, run the
  application with the -Djava.security.debug=access,failure flag
  to dump the name of permission checks that are failing. When
  you see a permission fail, add it back to the security file and
  try again. Warning: This will take a while! But, if you
  investigate each permission as you go, you will gain an 
  intimate understanding of how JAAS works.

To learn more about JAAS 1.0, see the Java Authentication and
Authorization Service (JAAS) 1.0 page: 
( http://java.sun.com/products/jaas/index-10.html ). Scroll down 
on that page to the "More Info" section for several useful links.

The 1.4 version of Java 2 Platform, Standard Edition incorporates 
JAAS. A beta version of J2SE(tm) version 1.4 is available for
download at http://java.sun.com/j2se/1.4/

.  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .

- NOTE

Sun respects your online time and privacy. The Java Developer 
Connection mailing lists are used for internal Sun Microsystems(tm) 
purposes only. You have received this email because you elected 
to subscribe. To unsubscribe, go to the Subscriptions page 
(http://developer.java.sun.com/subscription/), uncheck the 
appropriate checkbox, and click the Update button.

As of May  22, 2001, Sun Microsystems updated its Privacy Policy 
(http://sun.com/privacy) to give you a better understanding of 
Sun's Privacy Policy and Practice. If you have any questions, 
contact privacy@sun.com.


- SUBSCRIBE

To subscribe to a JDC newsletter mailing list, go to the 
Subscriptions page (http://developer.java.sun.com/subscription/), 
choose the newsletters you want to subscribe to, and click Update.


- FEEDBACK
Comments? Send your feedback on the JDC Tech Tips to:

jdc-webmaster@sun.com


- ARCHIVES
You'll find the JDC Tech Tips archives at:

http://java.sun.com/jdc/TechTips/index.html


- COPYRIGHT
Copyright 2001 Sun Microsystems, Inc. All rights reserved.
901 San Antonio Road, Palo Alto, California 94303 USA.

This document is protected by copyright. For more information, see:

http://java.sun.com/jdc/copyright.html



- LINKS TO NON-SUN SITES
The JDC Tech Tips may provide, or third parties may provide, 
links to other Internet sites or resources. Because Sun has no 
control over such sites and resources, You acknowledge and agree 
that Sun is not responsible for the availability of such external 
sites or resources, and does not endorse and is not responsible 
or liable for any Content, advertising, products, or other 
materials on or available from such sites or resources. Sun will 
not be responsible or liable, directly or indirectly, for any 
damage or loss caused or alleged to be caused by or in connection 
with use of or reliance on any such Content, goods or services 
available on or through any such site or resource.


JDC Tech Tips 
July 27, 2001

Sun, Sun Microsystems, Java, Java Developer Connection, and J2SE
are trademarks or registered trademarks of Sun Microsystems, Inc. 
in the United States and other countries.








	To use our one-click unsubscribe facility, select the following URL:
	http://hermes.java.sun.com/unsubscribe?623340616925952587
