This tutorial expands the program and policy file developed in the JAAS Authentication tutorial to demonstrate the JAAS authorization component, which ensures the authenticated caller has the access control rights (permissions) required to do subsequent security-sensitive operations. Since the authorization component requires that the user authentication first be completed, please read the JAAS Authentication tutorial first if you have not already done so.
The rest of this tutorial consists of the following sections:
If you want to first see the tutorial code in action, you can skip directly to Running the Authorization Tutorial Code and then go back to the other sections to learn more.
JAAS authorization extends the existing Java security
architecture that uses a security policy to specify what access rights
are granted to executing code. That architecture, introduced in the
Java 2 platform, is code-centric. That is, the permissions
are granted based on code characteristics: where the code is coming
from and whether it is digitally signed and if so by whom. We saw
an example of this in the jaasacn.policy
file used in
the JAAS Authentication tutorial. That
file contains the following:
grant codebase "file:./JaasAcn.jar" { permission javax.security.auth.AuthPermission "createLoginContext.JaasSample"; };
This grants the code in the JaasAcn.jar
file,
located in the current directory, the specified permission. (No
signer is specified, so it doesn't matter whether the code is
signed or not.)
JAAS authorization augments the existing code-centric access controls with new user-centric access controls. Permissions can be granted based not just on what code is running but also on who is running it.
When an application uses JAAS authentication to authenticate the user (or other entity such as a service), a Subject is created as a result. The purpose of the Subject is to represent the authenticated user. A Subject is comprised of a set of Principals, where each Principal represents an identity for that user. For example, a Subject could have a name Principal ("Susan Smith") and a Social Security Number Principal ("987-65-4321"), thereby distinguishing this Subject from other Subjects.
Permissions can be granted in the policy to specific Principals. After the user has been authenticated, the application can associate the Subject with the current access control context. For each subsequent security-checked operation, (a local file access, for example), the Java runtime will automatically determine whether the policy grants the required permission only to a specific Principal and if so, the operation will be allowed only if the Subject associated with the access control context contains the designated Principal.
To make JAAS authorization take place, the following is required:
Policy file
grant
statements can now optionally include one or
more Principal fields. Inclusion of a Principal field indicates
that the user or other entity represented by the specified
Principal, executing the specified code, has the designated
permissions.
Thus, the basic format of a grant
statement is
now
grant <signer(s) field>, <codeBase URL> <Principal field(s)> { permission perm_class_name "target_name", "action"; .... permission perm_class_name "target_name", "action"; };where each of the signer, codeBase and Principal fields is optional and the order between the fields doesn't matter.
A Principal field looks like the following:
Principal Principal_class "principal_name"
That is, it is the word "Principal" (where case doesn't matter) followed by the (fully qualified) name of a Principal class and a principal name.
A Principal class is a class that implements the java.security.Principal
interface. All Principal objects have an associated name that can
be obtained by calling their getName
method. The
format used for the name is dependent on each Principal
implementation.
The type of Principal placed in the Subject created by the
Kerberos authentication mechanism used by this tutorial is
javax.security.auth.kerberos.KerberosPrincipal
, so
that is what should be used as the
Principal_class
part of our grant
statement's Principal designation. User names for
KerberosPrincipal
s are of the form "name@realm". Thus,
if the user name is "mjones" and the realm is "KRBNT-OPS.ABC.COM",
the full principal_name
designation to use in
the grant
statement is "mjones@KRBNT-OPS.ABC.COM".
It is possible to include more than one Principal field in a
grant
statement. If multiple Principal fields are
specified, then the permissions in that grant
statement are granted only if the Subject associated with the
current access control context contains all of those
Principals.
To grant the same set of permissions to different Principals,
create multiple grant
statements where each lists the
permissions and contains a single Principal field designating one
of the Principals.
The policy file for this tutorial includes one
grant
statement with a Principal field:
grant codebase "file:./SampleAction.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"; };where you substitute your Kerberos user name (complete with "@" and realm) for "
your_user_name@your_realm
".
This specifies that the indicated permissions are granted to the
specified principal executing the code in
SampleAction.jar
.
To create and associate a Subject with an access control context, you need the following:
doAs
method from the Subject class must
be called, passing it an authenticated Subject and a java.security.PrivilegedAction
or java.security.PrivilegedExceptionAction.
(See API for Privileged
Blocks for a comparison of PrivilegedAction and
PrivilegedExceptionAction.) The doAs
method associates
the provided Subject with the current access control context and
then invokes the run
method from the action. The
run
method implementation contains all the code to be
executed as the specified Subject. The action thus executes as the
specified Subject.
The static doAsPrivileged
method from the Subject
class may be called instead of the doAs
method. In
addition to the parameters passed to doAs
,
doAsPrivileged
requires a third parameter: an
AccessControlContext. Unlike doAs
, which associates
the provided Subject with the current access control context,
doAsPrivileged
associates the Subject with the
provided access control context. See doAs vs. doAsPrivileged
in the JAAS Reference Guide for a comparison of those methods.
The code for this tutorial consists of two files:
JaasAcn.java
from the JAAS
Authentication tutorial except for the additional code needed
to call Subject.doAsPrivileged
.run
method that contains all the code we want to be
executed with Principal-based authorization checks.JaasAzn.java is exactly the same as
the JaasAcn.java
code used in the previous tutorial
except with three statements added at the end of the
main
method, after the authentication is done. These
statements result in (1) association of a Subject representing the
authenticated user with the current access control context and (2)
execution of the code in the run
method of
SampleAction. Associating the Subject with the access control
context enables security-sensitive operations in the SampleAction
run
method (and any code it invokes directly or
indirectly) to be executed if a Principal representing the
authenticated user is granted the required permissions in the
current policy.
Like JaasAcn.java
, JaasAzn.java
instantiates a LoginContext lc
and calls its
login
method to perform the authentication. If
successful, the authenticated Subject (which includes a Principal
representing the user) is obtained by calling the LoginContext's
getSubject
method:
Subject mySubject = lc.getSubject();
The main
method then calls
Subject.doAsPrivileged
, passing it the authenticated
Subject mySubject
, a PrivilegedAction (SampleAction)
and a null
AccessControlContext, as described in the
following.
The SampleAction class is instantiated via the following:
PrivilegedAction action = new SampleAction();
The call to Subject.doAsPrivileged
is performed
via:
Subject.doAsPrivileged(mySubject, action, null);
The doAsPrivileged
method invokes execution of the
run
method in the PrivilegedAction action
(SampleAction) to initiate execution of the rest of the code, which
is considered to be executed on behalf of the Subject
mySubject
.
Passing null
as the AccessControlContext (third)
argument to doAsPrivileged
indicates that
mySubject
should be associated with a new empty
AccessControlContext. The result is that security checks occurring
during execution of SampleAction will only require permissions for
the SampleAction code itself (or other code it invokes), running as
mySubject
. Note that the caller of
doAsPrivileged
(and the callers on the execution stack
at the time doAsPrivileged
was called) do not require
any permissions while the action executes.
SampleAction.java contains the
SampleAction class. This class implements
java.security.PrivilegedAction
and has a
run
method that contains all the code we want to be
executed as the Subject mySubject
. For this tutorial,
we will perform three operations, each of which cannot be done
unless code has been granted required permissions. We will:
java.home
system
property,user.home
system
property, andfoo.txt
exists in the current directory.Here is the code:
import java.io.File; import java.security.PrivilegedAction; public class SampleAction implements PrivilegedAction { public Object run() { 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."); return null; } }
The login configuration file used for this tutorial can be exactly the same as that used by the JAAS Authentication tutorial. Thus we can use jaas.conf, which contains just one entry:
JaasSample { com.sun.security.auth.module.Krb5LoginModule required; };
This entry is named "JaasSample" and that is the name that both
our tutorial applications JaasAcn
and
JaasAzn
use to refer to it. 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.
This authorization tutorial contains two classes,
JaasAzn
and SampleAction
. The code in
each class contains some security-sensitive operations and thus
relevant permissions are required in a policy file in order for the
operations to be executed.
The main method of the JaasAzn
class does two
operations for which permissions are required. It
doAsPrivileged
static method of the
Subject class.The LoginContext creation is exactly the same as was done in the
authentication tutorial, and it thus needs the same
javax.security.auth.AuthPermission
permission with
target "createLoginContext.JaasSample
".
In order to call the doAsPrivileged
method of the
Subject class, you need to have a
javax.security.auth.AuthPermission
with target
"doAsPrivileged
".
Assuming the JaasAzn
class is placed in a JAR file
named JaasAzn.jar
, these permissions can be granted to
the JaasAzn
code via the following grant
statement in the policy file:
grant codebase "file:./JaasAzn.jar" { permission javax.security.auth.AuthPermission "createLoginContext.JaasSample"; permission javax.security.auth.AuthPermission "doAsPrivileged"; };
The SampleAction
code does three operations for
which permissions are required. It
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
SampleAction.class
, which we will place in a JAR file
named SampleAction.jar
. However, for this particular
grant
statement we want to grant the permissions not
just to the code but to a specific user executing the code,
to demonstrate how to restrict access to a particular user.
Thus, as explained in How Do You Make
Principal-Based Policy File Statements?, our grant
statement looks like the following:
grant codebase "file:./SampleAction.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"; };You 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 is jaasazn.policy.
To execute our JAAS authorization tutorial code, all you have to do is
jaasazn.policy
with your user name and realm.SampleAction.java
and
JaasAzn.java
:
javac SampleAction.java JaasAzn.java
JaasAzn.jar
containing
JaasAzn.class
:
jar -cvf JaasAzn.jar JaasAzn.class
SampleAction.jar
containing SampleAction.class
:
jar -cvf SampleAction.jar SampleAction.class
JaasAzn
application, specifying
-classpath
clause that classes
should be searched for in the JaasAzn.jar
and
SampleAction.jar
JAR files,-Djava.security.manager
that a security manager
should be installed,-Djava.security.krb5.realm=<your_realm>
that your Kerberos realm is the one specified.-Djava.security.krb5.kdc=<your_kdc>
that
your Kerberos KDC is the one specified.-Djava.security.policy=jaasazn.policy
that the
policy file to be used is jaasazn.policy
, and-Djava.security.auth.login.config=jaas.conf
that the login configuration file to be used is
jaas.conf
.Below are the full commands to use for both Microsoft Windows
and Solaris, Linux, and Mac OS X systems.
The only difference is that on Windows systems
you use semicolons to separate classpath items, while you use
colons for that purpose on Solaris, Linux, and Mac OS X.
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 JaasAzn.jar;SampleAction.jar -Djava.security.manager -Djava.security.krb5.realm=<your_realm> -Djava.security.krb5.kdc=<your_kdc> -Djava.security.policy=jaasazn.policy -Djava.security.auth.login.config=jaas.conf JaasAzn
Here is the full command for Solaris, Linux, and Mac OS X systems:
java -classpath JaasAzn.jar:SampleAction.jar -Djava.security.manager -Djava.security.krb5.realm=<your_realm> -Djava.security.krb5.kdc=<your_kdc> -Djava.security.policy=jaasazn.policy -Djava.security.auth.login.config=jaas.conf JaasAzn
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 Solaris, Linux, and Mac OS X) and then run that file to execute the command.
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."
For login troubleshooting suggestions, see Troubleshooting.
Once authentication is successfully completed, the rest of the
program (in SampleAction
) will be executed on behalf
of you, the user, requiring you to have been granted appropriate
permissions. The jaasazn.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.