Java Authentication and Authorization Service (JAAS) Reference Guide

You can use JAAS for the authentication of users, to reliably and securely determine who is currently executing Java code.

JAAS implements a Java version of the standard Pluggable Authentication Module (PAM) framework.

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 or technologies, or LoginModule(s), to be used in performing the authentication. Typical LoginModules may prompt for and verify a user name and password. Others may read and verify a voice or fingerprint sample.

The user or service executing the code is represented by a Subject object after it has been authenticated. The Subject is updated by a LoginModule with relevant Principals and credentials if authentication succeeds. An application or library can use the credentials stored in the Subject to make subsequent authorization decisions.

Who Should Read This Document

This document is intended for experienced developers who require the ability to design applications constrained by a Subject-based security model. It is also intended to be read by LoginModule developers (developers implementing an authentication technology) prior to reading the Java Authentication and Authorization Service (JAAS): LoginModule Developer's Guide.

You may wish to first read JAAS Authentication Tutorial 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.

Related Documentation

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.

The JAAS Authentication Tutorial can be run by everyone.

JAAS Authentication is a similar tutorial that demonstrates the use of a Kerberos LoginModule. It requires a Kerberos installation. It's part of Introduction to JAAS and Java GSS-API Tutorials that utilize Kerberos as the underlying technology for authentication and secure communication.

Core Classes and Interfaces

The JAAS-related core classes and interfaces can be broken into two categories: Common and Authentication.

Common Classes

Common classes are those shared by both the JAAS authentication and authorization components.

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.

Subject

To authorize access to resources, applications first need to authenticate the source of the request. The JAAS framework defines the term subject to represent the source of a request. A subject may be any entity, such as a person or a service. Once the subject is authenticated, a javax.security.auth.Subject is populated with associated identities, or Principals. A Subject may have many Principals. 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; see the section 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.

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) Sets of Principals and credentials. The second constructor creates a Subject with the specified Sets of Principals 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 Sets 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();

Once in a read-only state, any attempt to add or remove Principals 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 Principals associated with a Subject, two methods are available:

public Set getPrincipals();
public Set getPrincipals(Class c);

The first method returns all Principals contained in the Subject, while the second method only returns those Principals 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 Principals.

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:

Only the sets returned through 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 through 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.

The following method enables you to perform an action as a specified Subject:

public static <T> T callAs(Subject subject, Callable<T> action)

When you perform an action with the callAs method, the Subject is bound to the period of execution. The following method returns the Subject associated with the period of execution of the current thread or null if no Subject has been set:

public static Subject current();

See The callAs and current Methods for Performing an Action as a Particular Subject for more information.

The Subject class also includes the following methods inherited from java.lang.Object.

public boolean equals(Object o);
public String toString();
public int hashCode();
The callAs and current Methods for Performing an Action as a Particular Subject

Call the following static method to perform an action as a particular Subject:

public static <T> T callAs(Subject subject, Callable<T> action)
    throws CompletionException

The example SampleAcn.java from JAAS Authentication Tutorial calls Subject.callAs(Subject, Callable<T>) as follows:

Subject.callAs(mySubject, anotherAction);

In this example, the argument anotherAction accesses the Subject mySubject with the method Subject.current():

Callable<Void> anotherAction = () -> {
            
    // Retrieve the current subject
    Subject s = Subject.current();
    System.out.println("\nCurrent subject: " + s);
            
    // Add a new Principal to the current subject
    Random r = new Random();
    String pn = Integer.toString(r.nextInt());
    Principal p = new sample.principal.SamplePrincipal(pn);
            
    System.out.println("\nAdding principal " + pn);
    s.getPrincipals().add(p);         
            
    // List the current subject's Principals
    System.out.println("\nAuthenticated user has the following Principals:");
    Iterator pi = s.getPrincipals().iterator();

    while (pi.hasNext()) {
        Principal nextp = (Principal)pi.next();
        System.out.println("\t" + nextp.toString());            
    }

    return null;            
};  

If a child thread starts and terminates within the execution of its parent's thread using structured concurrency, then the child thread can access the parent thread's current Subject with the Subject.current() method. The following example is from SampleAcn.java:

Callable<Void> addRandomPrincipal = () -> {
    
    Subject s = Subject.current();
    
    // Add a new Principal
    Random r = new Random();
    String pn = Integer.toString(r.nextInt());
    Principal p = new sample.principal.SamplePrincipal(pn);
    
    System.out.println("\nAdding principal " + pn);
    s.getPrincipals().add(p);         
    return null;
};

Callable<Void> structuredAction = () -> {
    try (var scope = new StructuredTaskScope<>()) {
        scope.fork(addRandomPrincipal);
        scope.fork(addRandomPrincipal);
        scope.fork(addRandomPrincipal);

        scope.join();
                
        Subject s = Subject.current();
        System.out.println("\nCurrent subject: " + s);
    
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return null;
};        
        
Subject.callAs(mySubject, structuredAction);

The method StructuredTaskScope.fork(Callable) starts a new thread in the task scope scope. This method returns a StructuredTaskScope.Subtask or a forked subtask. The example creates three forked subtasks. Each subtask obtains the parent thread's current Subject with the Subject.current() method, then adds a new principal to the Subject The method StructuredTaskScope.join() waits for the subtasks in scope to finish before continuing. The example then prints the Subject, which now contains three additional principals.

See Running the JAAS Authentication Tutorial Code to view the output from this example.

Note:

The class StructuredTaskScope is part of the structured concurrency API, which is a preview feature. A preview feature is a feature whose design, specification, and implementation are complete, but is not permanent. A preview feature may exist in a different form or not at all in future Java SE releases. To compile and run code that contains preview features, you must specify additional command-line options, such as --enable-preview -source 24. See Preview Language and VM Features in Java Platform, Standard Edition Java Language Updates and Structured Concurrency in Java Platform, Standard Edition Core Libraries.
Principals

As mentioned previously, once a Subject is authenticated, it is populated with associated identities, or Principals. A Subject may have many Principals. For example, a person may have a name Principal ("John Doe") and an SSN Principal ("123-45-6789"), which distinguish it from other Subjects. A Principal must implement the java.security.Principal and java.io.Serializable interfaces. See Subject for information about ways to update the Principals associated with a Subject.

Credentials

In addition to associated Principals, a Subject may own security-related attributes, which are referred to as credentials. A credential may contain information used to authenticate the subject to new services. Such credentials include passwords, Kerberos tickets, and public key certificates. Credentials might also contain data that simply enables the subject to perform certain activities. Cryptographic keys, for example, represent credentials that enable the subject to sign or encrypt data. Public and private credential classes are not part of the core JAAS class library. Any class, therefore, can represent a credential.

Public and private credential classes are not part of the core JAAS class library. Developers, however, may elect to have their credential classes implement two interfaces related to credentials: Refreshable and Destroyable.

Refreshable

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(): Determines whether the credential is current or valid
  • void refresh() throws RefreshFailedException: Updates or extends the validity of the credential
Destroyable

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

Authentication Classes and Interfaces

Authentication represents the process by which the identity of a subject is verified, and must be performed in a secure fashion; otherwise a perpetrator may impersonate others to gain access to a system. Authentication typically involves the subject demonstrating some form of evidence to prove its identity. Such evidence may be information only the subject would likely know or have (such as a password or fingerprint), or it may be information only the subject could produce (such as signed data using a private key).

To authenticate a subject (user or service), the following steps are performed:

  1. An application instantiates a LoginContext.
  2. The LoginContext consults a Configuration to load all of the LoginModules configured for that application.
  3. The application invokes the LoginContext's login method.
  4. The login method invokes all of the loaded LoginModules. Each LoginModule attempts to authenticate the subject. Upon success, LoginModules associate relevant Principals and credentials with a Subject object that represents the subject being authenticated.
  5. The LoginContext returns the authentication status to the application.
  6. If authentication succeeded, the application retrieves the Subject from the LoginContext.

The following sections describe the authentication classes.

LoginContext

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 LoginModules 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 LoginException

All 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 LoginModules 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.

See CallbackHandler 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 LoginModules are invoked to perform the authentication. If the authentication succeeded, the Subject (which may now hold Principals, 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());
}
LoginModule
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 LoginModules 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 LoginModules. 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 Java Authentication and Authorization Service (JAAS): LoginModule Developer's Guide for detailed step-by-step instructions.

CallbackHandler

In some cases a LoginModule must communicate with the user to obtain authentication information. LoginModules 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 LoginModules. 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 Callbacks, 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 Callbacks. 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

The javax.security.auth.callback package contains the Callback interface as well as several implementations. LoginModules may pass an array of Callbacks directly to the handle method of a CallbackHandler.

Please consult the various Callback APIs for more information on their use.

JAAS Authorization

Before the Security Manager was permanently disabled in JDK 24, the JAAS authorization component ensured users had the access control rights (or permissions) required to do the actions performed. Once the user or service executing the code was authenticated, the JAAS authorization component worked in conjunction with the core Java SE access control model and the Security Manager to protect access to sensitive resources.

This authorization mechanism is no longer supported because it's dependent on policy files and permissions, both of which have been removed or disabled now that the Security Manager is permanently disabled. Consequently, application code is responsible for performing authorization. This can be based on the principals and credentials that are stored inside a Subject after authentication.

For example, consider the example described in the JAAS Authentication Tutorial. The SampleLoginModule.java class, which implements the LoginModule interface, authenticates the user with a password. After it has authenticated the user, information (such as principals and credentials) can be extracted from the Subject and used for subsequent authorization decisions. The SampleAcn.java class runs the Callable anotherAction with the authenticated Subject with the Subject.callAs method:

Subject.callAs(mySubject, anotherAction);

Let's assume that the current Subject has one principal. The following example adds code to an excerpt from SampleAcn.java that retrieves this principal and grants access based on the principal's identity:

Callable<Void> anotherAction = () -> {
                
    Subject s = Subject.current();
    System.out.println("\nCurrent subject: " + s);
                
    Optional<Principal> principal = s.getPrincipals().stream().findFirst();

    // Authorize principal
    if (principal.isPresent() &&
        principal.get().getName().equals("Duke")) {
        // Grant access (code not shown)
        // ...
    }
}

Appendix A: JAAS Settings in the java.security Security Properties File

A number of JAAS-related settings can be configured in the java.security master Security Properties file, which is located in the conf/security directory of the JDK.

JAAS adds two new security properties to java.security:

  • login.configuration.provider
  • login.config.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 login.configuration.provider Security Property. The default java.security file also lists a value for the login.config.url.n Security Property, but it is commented out. In the following example, it is not commented.

#
# Class to instantiate as the javax.security.auth.login.Configuration
# provider.
#
login.configuration.provider=sun.security.provider.ConfigFile

#
# Default login configuration file
#
login.config.url.1=file:${user.home}/.java.login.config

Note:

Modifications made to this file may be overwritten by subsequent JDK 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.

Login Configuration Provider

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.Config

If 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.

Login Configuration URLs

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

Appendix B: JAAS Login Configuration File

JAAS authentication is performed in a pluggable fashion, so Java applications can remain independent from underlying authentication technologies. Configuration information such as the desired authentication technology is specified at runtime. 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, ConfigFile, gets its configuration information from login configuration files. For details about the default login Configuration implementation provided with JAAS, see the com.sun.security.auth.login.ConfigFile class.

Login Configuration File Structure and Contents

A login configuration file consists of one or more entries, each specifying which underlying authentication technology should be used for a particular application or applications. The structure of each entry is the following:

<name used by application to refer to this entry> { 
    <LoginModule> <flag> <LoginModule options>;
    <optional additional LoginModules, flags and options>;
};

Thus, each login configuration file entry consists of a name followed by one or more LoginModule-specific entries, where each LoginModule-specific entry is terminated by a semicolon and the entire group of LoginModule-specific entries is enclosed in braces. Each configuration file entry is terminated by a semicolon.

Example 6-1 Login Configuration File for JAAS Authentication Tutorial

As an example, the login configuration file used for the JAAS Authentication Tutorial tutorial contains just one entry, which is

Sample {
   sample.module.SampleLoginModule required debug=true;
};

Here, the entry is named Sample and that is the name that the JAAS Authentication tutorial application (SampleAcn.java) uses to refer to this entry. The entry specifies that the LoginModule to be used to do the user authentication is the SampleLoginModule in the sample.module package and that this SampleLoginModule is required to "succeed" in order for authentication to be considered successful. The SampleLoginModule succeeds only if the name and password supplied by the user are the ones it expects (testUser and testPassword, respectively).

The name for an entry in a login configuration file is the name that applications use to refer to the entry when they instantiate a LoginContext, as described in JAAS Authentication Tutorial in the JAAS authentication tutorial. The name can be whatever name the application developer wishes to use. Here, the term "application" refers to whatever code does the JAAS login.

The specified LoginModules are used to control the authentication process. Authentication proceeds down the list in the exact order specified, as described in the Configuration class.

The subparts of each LoginModule-specific entry are the following:

  • LoginModule: This specifies a class implementing the desired authentication technology. Specifically, the class must be a subclass of the LoginModule class, which is in the javax.security.auth.spi package. A typical LoginModule may prompt for and verify a user name and password, as is done by the SampleLoginModule (in the sample.module package) used for these tutorials. Any vendor can provide a LoginModule implementation that you can use. Some implementations are supplied with the JDK from Oracle. You can view the reference documentation for the various LoginModules, all in the com.sun.security.auth package:

  • flag: The flag value indicates whether success of the preceding LoginModule is required, requisite, sufficient, or optional. If there is just one LoginModule-specific entry, as there is in our tutorials, then the flag for it should be "required". The options are described in more detail in the Configuration class.

  • LoginModule options: If the specified LoginModule implementation has options that can be set, you specify any desired option values here. This is a space-separated list of values which are passed directly to the underlying LoginModule. Options are defined by the LoginModule itself, and control the behavior within it. For example, a LoginModule may define options to support debugging/testing capabilities.

    The correct way to specify options in the configuration file is by using a name-value pairing, for example debug=true, where the option name (in this case, debug) and value (in this case, true) should be separated by an equals symbol.

Example 6-2 Login Configuration File Demonstrating required, sufficient, requisite, and optional Flags

The following is a sample login configuration file that demonstrates the required, sufficient, requisite, and optional flags. See the Configuration class for more information about these flags.

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 following table:

Table 6-1 Login2 Authentication Status

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

* = trivial value due to control returning to the application because a previous requisite module failed or a previous sufficient module succeeded.

Where to Specify Which Login Configuration File Should Be Used

The configuration file to be used can be specified in one of two ways:

  1. On the command line.

    You can use a -Djava.security.auth.login.config interpreter command line argument to specify the login configuration file that should be used. We use this approach for all the tutorials. For example, we run our SampleAcn application in the JAAS Authentication Tutorial using the following command, which specifies that the configuration file is the sample_jaas.config file in the current directory:

    java -Djava.security.auth.login.config==sample_jaas.config sample.SampleAcn
    

    Note:

    If you use a single equals sign (=) with the java.security.auth.login.config system property (instead of a double equals sign (==)), then the configurations specified by both this system property and the java.security file are used.

  2. In the Java Security Properties file.

    An alternate approach to specifying the location of the login configuration file is to indicate its URL as the value of a login.config.url.n property in the security properties file. The Security Properties file is the java.security file located in the conf/security directory of the JDK.

    Here, n indicates a consecutively-numbered integer starting with 1. Thus, if desired, you can specify more than one login configuration file by indicating one file's URL for the login.config.url.1 property, a second file's URL for the login.config.url.2 property, and so on. If more than one login configuration file is specified (that is, if n > 1), then the files are read and concatenated into a single configuration.

    Here is an example of what would need to be added to the security properties file in order to indicate the sample_jaas.config login configuration file used by this tutorial. This example assumes the file is in the C:\AcnTest directory on Windows:

    login.config.url.1=file:C:/AcnTest/sample_jaas.config

    (Note that URLs always use forward slashes, regardless of what operating system the user is running.)