This guide covers the following topics:
The Java Authentication and Authorization Service (JAAS) was introduced as an optional package (extension) to the Java 2 SDK, Standard Edition (J2SDK), v 1.3. JAAS was integrated into the J2SDK 1.4.
JAAS can be used for two purposes:
JAAS implements a Java version of the standard Pluggable Authentication Module (PAM) framework. See Making Login Services Independent from Authentication Technologies for further information.
Traditionally Java has provided codesource-based access controls (access controls based on where the code originated from and who signed the code). It lacked, however, the ability to additionally enforce access controls based on who runs the code. JAAS provides a framework that augments the Java security architecture with such support.
JAAS authentication is performed in a pluggable
fashion. This permits applications to remain independent from
underlying authentication technologies. New or updated
authentication technologies can be plugged under an application
without requiring modifications to the application itself.
Applications enable the authentication process by instantiating a
LoginContext
object, which in turn references a
Configuration
to determine the authentication
technology(ies), or LoginModule
(s),
to be used in performing the authentication. Typical
LoginModule
s may prompt for and verify a user name
and password. Others may read and verify a voice or fingerprint
sample.
Once the user or service executing the code has been
authenticated, the JAAS authorization component works in
conjunction with the core Java SE access control model to protect
access to sensitive resources. Unlike in the J2SDK 1.3 and
earlier, where access control decisions are based solely on code
location and code signers (a CodeSource
),
in the J2SDK 1.4 access control decisions are based both on the
executing code's CodeSource
and on the user
or service running the code, who is represented by a Subject
object. The Subject
is updated by a
LoginModule
with relevant Principal
s
and credentials if authentication succeeds.
This document is intended for experienced developers who
require the ability to design applications constrained by a
CodeSource
-based and Subject
-based
security model. It is also intended to be read by LoginModule
developers (developers implementing an authentication technology)
prior to reading the JAAS
LoginModule Developer's Guide.
You may wish to first read the JAAS Authentication and JAAS Authorization tutorials to get an overview of how to use JAAS and to see sample code in action, and then return to this document for further information.
This document assumes you have already read the following:
A supplement to this guide is the JAAS LoginModule Developer's Guide,
intended for experienced programmers who require the ability to
write a LoginModule
implementing an authentication technology.
If you wish to learn more about the standard Pluggable Authentication Module (PAM) framework (JAAS implements a Java version of PAM), see Making Login Services Independent from Authentication Technologies.
The following tutorials for JAAS authentication and authorization can be run by everyone:
Similar tutorials for JAAS authentication and authorization, but which demonstrate the use of a Kerberos LoginModule and thus which require a Kerberos installation, can be found at
These two tutorials are a part of the Java GSS-API and JAAS sequence of tutorials that utilize Kerberos as the underlying technology for authentication and secure communication.
The key JAAS class is javax.security.auth.Subject
,
which represents a grouping of related information for a single
entity such as a person. It encompasses the entity's Principals, public credentials, and private
credentials.
Note that the java.security.Principal
interface
is used to represent a Principal. Also note that a credential, as
defined by JAAS, may be any Object.
javax.security.auth.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 SSN
Principal
("123-45-6789"), which distinguish it from
other subjects.
A Subject
may also own security-related
attributes, which are referred to as credentials.
Sensitive credentials that require special protection, such as
private cryptographic keys, are stored within a private
credential Set
. Credentials intended to be shared,
such as public key certificates, are stored within a public
credential Set
. Different permissions (described
below) are required to access and modify the different credential
Set
s.
Subjects are created using these constructors:
public Subject(); public Subject(boolean readOnly, Set principals, Set pubCredentials, Set privCredentials);The first constructor creates a
Subject
with empty
(non-null) Set
s of Principal
s and
credentials. The second constructor creates a
Subject
with the specified Set
s of
Principal
s and credentials. It also has a boolean
argument which can be used to make the Subject
read-only. In a read-only Subject
, the
Principal
and credential Set
s are
immutable.
An application writer does not have to instantiate a
Subject
. If the application instantiates a
LoginContext
and does not pass a
Subject
to the LoginContext
constructor, the LoginContext
instantiates a new
empty Subject
. See the LoginContext section.
If a Subject
was not instantiated to be in a
read-only state, it can be set read-only by calling the following
method:
public void setReadOnly();A
javax.security.auth.AuthPermission
with target
"setReadOnly" is required to invoke this method. Once in a
read-only state, any attempt to add or remove
Principal
s or credentials will result in an
IllegalStateException
being thrown.
The following method may be called to test a
Subject
's read-only state:
public boolean isReadOnly();
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
, while the second method only returns
those Principal
s that are an instance of the
specified Class c
, or an instance of a subclass of
Class c
. An empty set will be returned if the
Subject
does not have any associated
Principal
s.
To retrieve the public credentials associated with a
Subject
, these methods are available:
public Set getPublicCredentials(); public Set getPublicCredentials(Class c);
The behavior of these methods is similar to that for the
getPrincipals
methods, except in this case the
public credentials are being obtained.
To access private credentials associated with a
Subject
, the following methods are available:
public Set getPrivateCredentials(); public Set getPrivateCredentials(Class c);
The behavior of these methods is similar to that for the
getPrincipals
and getPublicCredentials
methods.
To modify or operate upon a Subject
's
Principal
Set
, public credential
Set
, or private credential Set
, callers
use the methods defined in the java.util.Set
class. The following example demonstrates this:
Subject subject; Principal principal; Object credential; . . . // add a Principal and credential to the Subject subject.getPrincipals().add(principal); subject.getPublicCredentials().add(credential);
Note: An AuthPermission
with target
"modifyPrincipals", "modifyPublicCredentials", or
"modifyPrivateCredentials" is required to modify the respective
Set
s. Also note that only the sets returned via the
getPrincipals()
,
getPublicCredentials()
, and
getPrivateCredentials()
methods with no arguments
are backed by the Subject
's respective internal
sets. Therefore any modification to the returned set affects the
internal sets as well. The sets returned via the
getPrincipals(Class c)
,
getPublicCredentials(Class c)
, and
getPrivateCredentials(Class c)
methods are not
backed by the Subject
's respective internal sets. A
new set is created and returned for each such method invocation.
Modifications to these sets will not affect the
Subject
's internal sets.
In order to iterate through a Set of private credentials, you
need a
javax.security.auth.PrivateCredentialPermission
to
access each credential. See the
PrivateCredentialPermission
API documentation
for further information.
A Subject
may be associated with an
AccessControlContext
(see the doAs
and
doAsPrivileged
method descriptions below). The
following method returns the Subject
associated with
the specified AccessControlContext
, or
null
if no Subject
is associated with
the specified AccessControlContext
.
public static Subject getSubject(final AccessControlContext acc);
An AuthPermission
with target "getSubject" is
required to call Subject.getSubject
.
The Subject
class also includes the following
methods inherited from java.lang.Object
.
public boolean equals(Object o); public String toString(); public int hashCode();
Subject
:
public static Object doAs(final Subject subject, final java.security.PrivilegedAction action); public static Object doAs(final Subject subject, final java.security.PrivilegedExceptionAction action) throws java.security.PrivilegedActionException;
Both methods first associate the specified
subject
with the current Thread's
AccessControlContext
, and then execute the
action
. This achieves the effect of having the
action
run as the subject
. The first
method can throw runtime exceptions but normal execution has it
returning an Object from the run
method of its
action
argument. The second method behaves similarly
except that it can throw a checked exception from its
PrivilegedExceptionAction run
method. An
AuthPermission
with target "doAs" is required to
call the doAs
methods.
Here is an example utilizing the first doAs
method. Assume that someone named "Bob" has been authenticated by
a LoginContext
(see the LoginContext section) and as a result a
Subject
was populated with a Principal
of class com.ibm.security.Principal
, and that
Principal
has the name "BOB". Also assume that a
SecurityManager has been installed, and that the following exists
in the access control policy (see the Policy
section for more details on the policy file).
// grant "BOB" permission to read the file "foo.txt" grant Principal com.ibm.security.Principal "BOB" { permission java.io.FilePermission "foo.txt", "read"; };
Here is the sample application code:
class ExampleAction implements java.security.PrivilegedAction { public Object run() { java.io.File f = new java.io.File("foo.txt"); // the following call invokes a security check if (f.exists()) { System.out.println("File foo.txt exists"); } return null; } } public class Example1 { public static void main(String[] args) { // Authenticate the subject, "BOB". // This process is described in the // LoginContext section. Subject bob; // Set bob to the Subject created during the // authentication process // perform "ExampleAction" as "BOB" Subject.doAs(bob, new ExampleAction()); } }
During execution, ExampleAction
will encounter a
security check when it makes a call to f.exists()
.
However, since ExampleAction
is running as "BOB",
and the policy (above) grants the necessary
FilePermission
to "BOB", the
ExampleAction
will pass the security check. If the
grant
statement in the policy is altered (adding an
incorrect CodeBase
or changing the
Principal
to "MOE", for example), then a
SecurityException
will be thrown.
The following methods also perform an action as a particular
Subject
.
public static Object doAsPrivileged( final Subject subject, final java.security.PrivilegedAction action, final java.security.AccessControlContext acc); public static Object doAsPrivileged( final Subject subject, final java.security.PrivilegedExceptionAction action, final java.security.AccessControlContext acc) throws java.security.PrivilegedActionException;
An AuthPermission
with target "doAsPrivileged" is
required to call the doAsPrivileged
methods.
The doAsPrivileged
methods behave exactly the
same as the doAs
methods, except that instead of
associating the provided Subject
with the current
Thread's AccessControlContext
, they use the provided
AccessControlContext
. In this way, actions can be
restricted by AccessControlContext
s different from
the current one.
An AccessControlContext
contains information
about all the code executed since the
AccessControlContext
was instantiated, including the
code location and the permissions the code is granted by the
policy. In order for an access control check to succeed, the
policy must grant each code item referenced by the
AccessControlContext
the required permissions.
If the AccessControlContext
provided to
doAsPrivileged
is null
, then the action
is not restricted by a separate
AccessControlContext
. One example where this may be
useful is in a server environment. A server may authenticate
multiple incoming requests and perform a separate
doAs
operation for each request. To start each
doAs
action "fresh," and without the restrictions of
the current server AccessControlContext
, the server
can call doAsPrivileged
and pass in a
null
AccessControlContext
.
Principal
s may be
associated with a Subject
if authentication is
successful. Principal
s represent
Subject
identities, and must implement the java.security.Principal
and java.io.Serializable
interfaces. The Subject section describes
ways to update the Principal
s associated with a
Subject
.
Refreshable
and Destroyable
.
The javax.security.auth.Refreshable
interface provides the capability for a credential to
refresh itself. For example, a credential with a particular
time-restricted lifespan may implement this interface to allow
callers to refresh the time period for which it is valid. The
interface has two abstract methods:
boolean isCurrent();This method determines whether the credential is current or valid.
void refresh() throws RefreshFailedException;This method updates or extends the validity of the credential. The method implementation should perform an
AuthPermission("refreshCredential")
security check
to ensure the caller has permission to refresh the credential.
The javax.security.auth.Destroyable
interface provides the capability of destroying the
contents within a credential. The interface has two abstract
methods:
boolean isDestroyed();Determines whether the credential has been destroyed.
void destroy() throws DestroyFailedException;Destroys and clears the information associated with this credential. Subsequent calls to certain methods on this credential will result in an
IllegalStateException
being thrown. The method implementation should perform an
AuthPermission("destroyCredential")
security check
to ensure the caller has permission to destroy the credential.
LoginContext
.LoginContext
consults a
Configuration
to load all of the
LoginModule
s configured for that application.LoginContext
's
login
method.login
method invokes all of the loaded
LoginModule
s. Each LoginModule
attempts
to authenticate the subject. Upon success,
LoginModule
s associate relevant
Principal
s and credentials with a
Subject
object that represents the subject being
authenticated.LoginContext
returns the authentication
status to the application.Subject
from the LoginContext
.The authentication classes are described below.
The
javax.security.auth.login.LoginContext
class provides
the basic methods used to authenticate subjects, and provides 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, different
LoginModule
s can be plugged in under an application
without requiring any modifications to the application
itself.
LoginContext
offers four constructors from which
to choose:
public LoginContext(String name) throws LoginException; public LoginContext(String name, Subject subject) throws LoginException; public LoginContext(String name, CallbackHandler callbackHandler) throws LoginException public LoginContext(String name, Subject subject, CallbackHandler callbackHandler) throws LoginExceptionAll of the constructors share a common parameter:
name
. This argument is used by the
LoginContext
as an index into the login
Configuration to determine which LoginModule
s are
configured for the application instantiating the
LoginContext
. Constructors that do not take a
Subject
as an input parameter instantiate a new
Subject
. Null inputs are disallowed for all
constructors. Callers require an AuthPermission
with
target "createLoginContext.<name>" to instantiate a
LoginContext
. Here, <name> refers to the name
of the login configuration entry that the application references
in the name
parameter for the
LoginContext
instantiation.
See the CallbackHandler section
for information on what a CallbackHandler
is and
when you may need one.
Actual authentication occurs with a call to the following method:
public void login() throws LoginException;
When login
is invoked, all of the configured
LoginModule
s are invoked to perform the
authentication. If the authentication succeeded, the
Subject
(which may now hold Principal
s,
public credentials, and private credentials) can be retrieved by
using the following method:
public Subject getSubject();
To logout a Subject
and remove its authenticated
Principals
and credentials, the following method is
provided:
public void logout() throws LoginException;
The following code sample demonstrates the calls necessary to authenticate and logout a Subject:
// let the LoginContext instantiate a new Subject LoginContext lc = new LoginContext("entryFoo"); 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.err.println("authentication unsuccessful: " + le.getMessage()); }
The LoginModule
interface gives developers the ability to implement
different kinds of authentication technologies that can be
plugged in under an application. For example, one type of
LoginModule
may perform a user name/password-based
form of authentication. Other LoginModule
s may
interface to hardware devices such as smart cards or biometric
devices.
Note: If you are an application writer, you do not need to
understand the workings of LoginModule
s. All you
have to know is how to write your application and specify
configuration information (such as in a login configuration file)
such that the application will be able to utilize the LoginModule
specified by the configuration to authenticate the user.
If, on the other hand, you are a programmer who wishes to
write a LoginModule implementing an authentication technology,
see the JAAS
LoginModule
Developer's Guide for detailed
step-by-step instructions.
In some cases a LoginModule
must communicate with
the user to obtain authentication information.
LoginModule
s use a
javax.security.auth.callback.CallbackHandler for this
purpose. Applications implement the CallbackHandler
interface and pass it to the LoginContext
,
which forwards it directly to the underlying
LoginModule
s. A LoginModule
uses the
CallbackHandler
both to gather input from users
(such as a password or smart card pin number) or to supply
information to users (such as status information). By allowing
the application to specify the CallbackHandler
,
underlying LoginModules
can remain independent of
the different ways applications interact with users. For example,
the implementation of a CallbackHandler
for a GUI
application might display a window to solicit input from a user.
On the other hand, the implementation of a
CallbackHandler
for a non-GUI tool might simply
prompt the user for input directly from the command line.
CallbackHandler
is an interface with one method to
implement:
void handle(Callback[] callbacks) throws java.io.IOException, UnsupportedCallbackException;
The LoginModule
passes the CallbackHandler
handle
method an array of appropriate
Callback
s, for example a NameCallback
for the user name and a
PasswordCallback for the password, and the
CallbackHandler
performs the requested user
interaction and sets appropriate values in the
Callback
s. For example, to process a
NameCallback
, the CallbackHandler
may
prompt for a name, retrieve the value from the user, and call the
NameCallback
's setName
method to store
the name.
The
CallbackHandler
documentation has a lengthy
example not included in this document that readers may want to
examine.
Callback
interface as well as several
implementations. LoginModule
s may pass an array of
Callback
s directly to the handle
method
of a CallbackHandler.
Please consult the various Callback
APIs for more
information on their use.
To make JAAS authorization take place, granting access control permissions based not just on what code is running but also on who is running it, the following is required:
The Policy
abstract class and the
authorization-specific classes AuthPermission
and
PrivateCredentialPermission
are described below.
The java.security.Policy
class is an abstract class for representing the
system-wide access control policy. The Policy
API
was upgraded in the J2SDK 1.4 to support Principal
-based
queries.
As a default, the J2SDK provides a file-based subclass
implementation, which was upgraded to support
Principal
-based grant
entries in policy
files.
Policy files and the structure of entries within them are described in Default Policy Implementation and Policy File Syntax.
The javax.security.auth.AuthPermission
class encapsulates the basic permissions required for JAAS. An
AuthPermission
contains a name (also referred to as
a "target name") but no actions list; you either have the named
permission or you don't.
In addition to its inherited methods (from the java.security.Permission
class), an AuthPermission
has two public
constructors:
public AuthPermission(String name); public AuthPermission(String name, String actions);The first constructor creates a new
AuthPermission
with the specified name. The second constructor also creates a
new AuthPermission
object with the specified name,
but has an additional actions
argument which is
currently unused and should be null. This constructor exists
solely for the Policy
object to instantiate new
Permission
objects. For most other code, the first
constructor is appropriate.
Currently the AuthPermission
object is used to
guard access to the Policy
, Subject
,
LoginContext
, and Configuration
objects. Please refer to the AuthPermission
javadocs for the list of valid names that are supported.
The
javax.security.auth.PrivateCredentialPermission
class protects access to a Subject
's private
credentials and provides one public constructor:
public PrivateCredentialPermission(String name, String actions);Please refer to the PrivateCredentialPermission javadocs for more detailed information on this class.
The JAAS Authentication and JAAS Authorization tutorials contain the following samples:
sample_jaas.config
) as the class implementing the
desired underlying authentication. SampleLoginModule's user
authentication consists of simply verifying that the name and
password specified by the user have specific values.Principal
interface. It is used by SampleLoginModule.See the tutorials for detailed information about the applications, the policy files, and the login configuration file.
Application writers do not need to understand the code for SampleLoginModule.java or SamplePrincipal.java, as explained in the tutorials. Programmers who wish to write LoginModules can learn how to do so by reading the JAAS LoginModule Developer's Guide.
A number of JAAS-related settings can be configured in the
java.security
master security properties file, which
is located in the lib/security directory of the Java
runtime.
JAAS adds two new security properties to
java.security
:
login.configuration.provider
login.config.url.n
The following pre-existing properties are also relevant for JAAS users:
policy.provider
policy.url.n
The following example demonstrates how to configure these properties.
In this example, we leave the values provided in the default
java.security
file for the policy.provider
, policy.url.n
, and
login.configuration.provider
properties. The default java.security
file also
lists a value for the login.config.url.n property
, but it is commented out. In the example below, it is not commented.
... # # Class to instantiate as the javax.security.auth.login.Configuration # provider. # login.configuration.provider=com.sun.security.auth.login.ConfigFile # # Default login configuration file # login.config.url.1=file:${user.home}/.java.login.config # # Class to instantiate as the system Policy. This is the name of the class # that will be used as the Policy object. # policy.provider=sun.security.provider.PolicyFile # The default is to have a single system-wide policy file, # and a policy file in the user's home directory. policy.url.1=file:${java.home}/lib/security/java.policy policy.url.2=file:${user.home}/.java.policy ...
Note: Modifications made to this file may be overwritten by subsequent JRE updates.
However, an alternate java.security
properties file may be specified from the command line
via the system property java.security.properties=<URL>
.
This properties file appends to the system properties file. If both properties files specify values for the same key,
the value from command-line properties file is selected, as it is the last one loaded.
Also, specifying java.security.properties==<URL>
(using two equals signs), then that properties file
will completely override the system properties file.
To disable the ability to specify an additional properties file from the command line, set the key
security.overridePropertiesFile
to false
in the system properties file. It is set to true
by default.
The default JAAS login configuration implementation provided by Oracle gets its configuration information from files and expects the information to be provided in a specific format shown in the tutorials.
The default JAAS login configuration implementation can be
replaced by specifying the alternative provider class
implementation in the login.configuration.provider
property.
For example:
login.configuration.provider=com.foo.ConfigIf the Security property
login.configuration.provider
is not found, or is
left unspecified, then it is set to the default value:
login.configuration.provider=com.sun.security.auth.login.ConfigFile
Note that there is no means to dynamically set the login configuration provider from the command line.
If you are using a login configuration implementation that
expects the configuration information to be specified in files
(as does the default implementation from Oracle), the
location of the login configuration file(s) can be statically set
by specifying their respective URLs in the
login.config.url.n
property. 'n' is a
consecutively numbered integer starting with 1. If multiple
configuration files are specified (if n >= 2), they
will be read and unioned into one single configuration.
For example:
login.config.url.1=file:C:/config/.java.login.config login.config.url.2=file:C:/users/foo/.foo.login.config
If the location of the configuration files is not set in the
java.security
properties file, and also is not
specified dynamically from the command line (via the
-Djava.security.auth.login.config
option), JAAS
attempts to load a default configuration from
file:${user.home}/.java.login.config
The default policy implementation can be replaced by
specifying the alternative provider class implementation in the
policy.provider
property.
For example:
policy.provider=com.foo.PolicyIf the Security property
policy.provider
is not
found, or is left unspecified, then the Policy
is
set to the default value:
policy.provider=sun.security.provider.PolicyFile
Note that there is no means to dynamically set the policy provider from the command line.
The location of the access control policy files can be
statically set by specifying their respective URLs in the
auth.policy.url.n
property. 'n' is a
consecutively numbered integer starting with 1. If multiple
policies are specified (if n >= 2), they will be read
and unioned into one single policy.
For example:
policy.url.1=file:C:/policy/.java.policy policy.url.2=file:C:/users/foo/.foo.policy
If the location of the policy file(s) is not set in the
java.security
properties file, and is not specified
dynamically from the command line (via the
-Djava.security.policy
option), the access control
policy defaults to the same policy as that of the system policy
file installed with the J2SDK. That policy file
Login configurations are located using the
login.config.url.n
security properties found in the
java.security
file. For more information about this
property and the location of the java.security
file,
see Appendix A.
The default Configuration implementation,
ConfigFile
, gets its configuration information from
login configuration files. For details about the default login
Configuration implementation provided with JAAS, please consult
the javadocs for the
com.sun.security.auth.login.ConfigFile
class.
The following is a sample login configuration file.
Login1 { sample.SampleLoginModule required debug=true; }; Login2 { sample.SampleLoginModule required; com.sun.security.auth.module.NTLoginModule sufficient; com.foo.SmartCard requisite debug=true; com.foo.Kerberos optional debug=true; };
The application Login1 only has one configured
LoginModule, SampleLoginModule
. Therefore, an
attempt by Login1 to authenticate a subject (user or
service) will be successful if and only if the
SampleLoginModule
succeeds.
The authentication logic for the application Login2 is
easier to explain with the table below. Note: the
required
, sufficient
,
requisite
, and optional
flags are
described in the
Configuration
javadocs.
Module Class | Flag | Authentication Attempt 1 | Authentication Attempt 2 | Authentication Attempt 3 | Authentication Attempt 4 | Authentication Attempt 5 | Authentication Attempt 6 | Authentication Attempt 7 | Authentication Attempt 8 |
---|---|---|---|---|---|---|---|---|---|
SampleLoginModule | required | pass | pass | pass | pass | fail | fail | fail | fail |
NTLoginModule | sufficient | pass | fail | fail | fail | pass | fail | fail | fail |
SmartCard | requisite | * | pass | pass | fail | * | pass | pass | fail |
Kerberos | optional | * | pass | fail | * | * | pass | fail | * |
Overall Authentication | not applicable | pass | pass | pass | fail | fail | fail | fail | fail |