3 Using JAAS Authentication in Java Clients
The sections refer to sample code which is included in the WebLogic Server distribution at:
EXAMPLES_HOME\src\examples\security\jaas
The EXAMPLES_HOME
directory can be found at ORACLE_HOME
\wlserver\samples\server
.
The jaas
directory contains an instructions.html
file, ant
build files, a sample_jaas.config
file, and the following Java files:
-
BaseClient.java
-
BaseClientConstants.java
-
SampleAction.java
-
SampleCallbackHandler.java
-
SampleClient.java
-
TradeResult.java
-
TraderBean.java
You will need to look at the examples when reading the information in the following sections.
JAAS and WebLogic Server
The Java Authentication and Authorization Service (JAAS) is a standard extension to the security in the Java EE Development Kit. JAAS provides the ability to enforce access controls based on user identity. WebLogic Server provides JAAS as an alternative to the JNDI authentication mechanism. There are certain considerations when using JAAS authentication.
WebLogic Server clients use the authentication portion of the standard JAAS only. The JAAS LoginContext provides support for the ordered execution of all configured authentication provider LoginModule instances and is responsible for the management of the completion status of each configured provider.
Note the following considerations when using JAAS authentication for Java clients:
-
WebLogic Server clients can either use the JNDI login or JAAS login for authentication, however JAAS login is the preferred method.
-
While JAAS is the preferred method of authentication, the WebLogic-supplied LoginModule (
weblogic.security.auth.login.UsernamePasswordLoginModule
) only supports username and password authentication. Thus, for client certificate authentication (also referred to as two-way SSL authentication), you should use JNDI. To use JAAS for client certificate authentication, you must write a custom LoginModule that does certificate authentication.Note:
If you write your own LoginModule for use with WebLogic Server clients, have it call weblogic.security.auth.Authenticate.authenticate() to perform the login.
-
To perform a JAAS login from a remote Java client (that is, the Java client is not a WebLogic Server client), you may use the WebLogic-supplied LoginModule to perform the login. However, if you elect not to use the WebLogic-supplied LoginModule but decide to write your own instead, you must have it call the
weblogic.security.auth.Authenticate.authenticate()
method to perform the login. -
If you are using a remote, or perimeter, login system such as Security Assertion Markup Language (SAML), you do not need to call
weblogic.security.auth.Authenticate.authenticate()
. You only need to call theauthenticate()
method if you are using WebLogic Server to perform the logon.Note:
WebLogic Server provides full container support for JAAS authentication and supports full use of JAAS authentication and authorization in application code.
-
Within WebLogic Server, JAAS is called to perform the login. Each Authentication provider includes a LoginModule. This is true for servlet logins as well as Java client logins via JNDI or JAAS. The method WebLogic Server calls internally to perform the JAAS logon is
weblogic.security.auth.Authentication.authenticate()
. When using the Authenticate class,weblogic.security.SimpleCallbackHandler
may be a useful helper class. -
While WebLogic Server does not protect any resources using JAAS authorization (it uses WebLogic security), you can use JAAS authorization in application code to protect the application's own resources.
For more information about JAAS, see the JAAS documentation at http://www.oracle.com/technetwork/java/javase/jaas/index.html
.
JAAS Authentication Development Environment
WebLogic Server uses the JAAS classes to reliably and securely authenticate to the server. JAAS implements a Java version of the Pluggable Authentication Module (PAM) framework, which permits applications to remain independent from underlying authentication technologies. Therefore, the PAM framework allows the use of new or updated authentication technologies without requiring modifications to a Java application.
WebLogic Server uses JAAS for remote Java client authentication, and internally for authentication. Therefore, only developers of custom Authentication providers and developers of remote Java client applications need to be involved with JAAS directly. Users of Web browser clients or developers of within-container Java client applications (for example, those calling an EJB from a servlet) do not require direct use or knowledge of JAAS.
Note:
In order to implement security in a WebLogic client you must install the WebLogic Server software distribution kit on the Java client.
The following topics are covered in this section:
JAAS Authentication APIs
To implement Java clients that use JAAS authentication on WebLogic Server, you use a combination of Java EE application programming interfaces (APIs) and WebLogic APIs.
Table 3-1 lists and describes the Java API packages used to implement JAAS authentication. The information in Table 3-1 is taken from the Java API documentation and annotated to add WebLogic Server specific information. For more information on the Java APIs, see the Javadocs at http://docs.oracle.com/javase/8/docs/api/index.html
and http://docs.oracle.com/javaee/7/api/
.
Table 3-1 lists and describes the WebLogic APIs used to implement JAAS authentication. See Java API Reference for Oracle WebLogic Server.
Table 3-1 Java JAAS APIs
Java JAAS API | Description |
---|---|
The |
|
The After the caller instantiates a If the To log the For a sample implementation of this class, see Writing a Client Application Using JAAS Authentication. |
|
This is an abstract class for representing the configuration of LoginModules under an application. The In WebLogic Server, use a login configuration file instead of this class. For a sample configuration file, see Writing a Client Application Using JAAS Authentication. By default, WebLogic Server uses the configuration class, which reads from a configuration file. |
|
While application developers write to the Note: WebLogic Server provides an implementation of the LoginModule (
|
|
Implementations of this interface are passed to a
|
|
An application implements a
Underlying security services make requests for different types of information by passing individual |
Table 3-2 WebLogic JAAS APIs
WebLogic JAAS API | Description |
---|---|
An authentication class used to authenticate user credentials. The WebLogic implementation of the LoginModule, (
|
|
Underlying security services use this class to instantiate and pass a This callback passes the ContextHandler to LoginModule.login() methods. |
|
Underlying security services use this class to instantiate and pass a |
|
Underlying security services use this class to instantiate and pass a The WebLogic implementation of the
Note: Application developers should not use this class to retrieve URL information. Instead, they should use the weblogic.security.URLCallbackHandler. |
|
This class implements the WebLogic Server client For a sample implementation, see Writing a Client Application Using JAAS Authentication. |
|
The class used by application developers for returning a |
JAAS Client Application Components
At a minimum, a JAAS authentication client application includes the following components:
-
Java client
The Java client instantiates a
LoginContext
object and invokes the login by calling the object'slogin()
method. Thelogin()
method calls methods in each LoginModule to perform the login and authentication.The LoginContext also instantiates a new empty
javax.security.auth.Subject
object (which represents the user or service being authenticated), constructs the configured LoginModule, and initializes it with this newSubject
andCallbackHandler
.The LoginContext subsequently retrieves the authenticated Subject by calling the LoginContext's
getSubject
method. The LoginContext uses theweblogic.security.Security.runAs()
method to associate theSubject
identity with thePrivilegedAction
orPrivilegedExceptionAction
to be executed on behalf of the user identity. -
LoginModule
The LoginModule uses the
CallbackHandler
to obtain the user name and password and determines whether that name and password are the ones required.If authentication is successful, the LoginModule populates the Subject with a Principal representing the user. The Principal the LoginModule places in the Subject is an instance of
Principal
, which is a class implementing thejava.security.Principal
interface.You can write LoginModule files that perform different types of authentication, including username/password authentication and certificate authentication. A client application can include one LoginModule (the minimum requirement) or several LoginModules.
Note:
Use of the JAAS javax.security.auth.Subject.doAs methods in WebLogic Server applications do not associate the Subject with the client actions. You can use the doAs methods to implement Java EE security in WebLogic Server applications, but such usage is independent of the need to use the Security.runAs() method.
-
Callbackhandler
The
CallbackHandler
implements thejavax.security.auth.callback.CallbackHandler
interface. The LoginModule uses theCallbackHandler
to communicate with the user and obtain the requested information, such as the username and password. -
Configuration file
This file configures the LoginModule(s) used in the application. It specifies the location of the LoginModule(s) and, if there are multiple LoginModules, the order in which they are executed. This file enables Java applications to remain independent from the authentication technologies, which are defined and implemented using the LoginModule.
-
Action file
This file defines the operations that the client application will perform.
-
ant
build script (build.xml
)This script compiles all the files required for the application and deploys them to the WebLogic Server applications directories.
For a complete working JAAS authentication client that implements the components described here, see the JAAS sample application in EXAMPLES_HOME
\src\examples\security\jaas
, where EXAMPLES_HOME
represents the directory in which the WebLogic Server code examples are configured and can be found at ORACLE_HOME
\wlserver\samples\server
. For more information about the WebLogic Server code examples, see Sample Applications and Code Examples in Understanding Oracle WebLogic Server.
For more information on the basics of JAAS authentication, see JAAS Authentication Tutorial available at http://docs.oracle.com/javase/8/docs/technotes/guides/security/jaas/tutorials/GeneralAcnOnly.html
.
WebLogic LoginModule Implementation
The WebLogic implementation of the LoginModule
class (UsernamePasswordLoginModule.class
) is provided in the WebLogic Server distribution in the weblogic.jar
file, located in the WL_HOME\server\lib
directory.
Note:
WebLogic Server supports all callback types defined by JAAS as well as all callback types that extend the JAAS specification.
The WebLogic Server UsernamePasswordLoginModule
checks for existing system user authentication definitions prior to execution, and does nothing if they are already defined.
For more information about implementing JAAS LoginModules, see the LoginModule Developer's Guide at http://docs.oracle.com/javase/8/docs/technotes/guides/security/jaas/JAASLMDevGuide.html
JVM-Wide Default User and the runAs() Method
The first time you use the WebLogic Server implementation of the LoginModule (weblogic.security.auth.login.UsernamePasswordLoginModule
) to log on, the specified user becomes the machine-wide default user for the JVM (Java virtual machine). When you execute the weblogic.security.Security.runAs()
method, it associates the specified Subject
with the current thread's access permissions and then executes the action. If a specified Subject
represents a non-privileged user (users who are not assigned to any groups are considered non-privileged), the JVM-wide default user is used. Therefore, it is important make sure that the runAs()
method specifies the desired Subject
. You can do this using one of the following options:
-
Option 1: If the client has control of
main()
, implement the wrapper code shown in Example 3-1 in the client code. -
Option 2: If the client does not have control of
main()
, implement the wrapper code shown in Example 3-1 on each thread'srun()
method.
Example 3-1 runAs() Method Wrapper Code
import java.security.PrivilegedAction; import javax.security.auth.Subject; import weblogic.security.Security; public class client { public static void main(String[] args) { Security.runAs(new Subject(), new PrivilegedAction() { public Object run() { // //If implementing in client code, main() goes here. // return null; } }); } }
Writing a Client Application Using JAAS Authentication
To use JAAS in a WebLogic Server Java client for authentication, you implement the LoginModule
and the CallbackHandler
classes, write a configuration file that specifies which LoginModule classes to use, and perform other tasks.
Perform the following procedure to use JAAS in a WebLogic Server Java client to authenticate a subject:
-
Implement
LoginModule
classes for the authentication mechanisms you want to use with WebLogic Server. You will need a LoginModule class for each type of authentication mechanism. You can have multiple LoginModule classes for a single WebLogic Server deployment.Note:
Oracle recommends that you use the implementation of the LoginModule provided by WebLogic Server (weblogic.security.auth.login.UsernamePasswordLoginModule) for username/password authentication. You can write your own LoginModule for username/password authentication, however, do not attempt to modify the WebLogic Server LoginModule and reuse it. If you write your own LoginModule, you must have it call the weblogic.security.auth.Authenticate.authenticate() method to perform the login. If you use a remote login mechanism such as SAML, you do not need to call the authenticate() method. You only need to call authenticate() if you are using WebLogic Server to perform the logon.
The
weblogic.security.auth.Authenticate
class uses a JNDI Environment object for initial context as described in Table 3-1. -
Implement the
CallbackHandler
class that the LoginModule will use to communicate with the user and obtain the requested information, such as the username, password, and URL. The URL can be the URL of a WebLogic cluster, providing the client with the benefits of server failover. The WebLogic Server distribution provides aSampleCallbackHandler
which is used in the JAAS client sample. TheSampleCallbackHandler.java
code is available as part of the distribution in the directoryEXAMPLES_HOME
\src\examples\security\jaas
. TheEXAMPLES_HOME
directory can be found atORACLE_HOME
\wlserver\samples\server.
Note:
Instead of implementing your own CallbackHandler class, you can use either of two WebLogic-supplied CallbackHandler classes, weblogic.security.SimpleCallbackHandler or weblogic.security.URLCallbackHandler. For more information on these classes, see Java API Reference for Oracle WebLogic Server.
-
Write a configuration file that specifies which LoginModule classes to use for your WebLogic Server and in which order the LoginModule classes should be invoked. See the following sample configuration file used in the JAAS client sample provided in the WebLogic Server distribution.
/** Login Configuration for the JAAS Sample Application **/ Sample { weblogic.security.auth.login.UsernamePasswordLoginModule required debug=false; };
-
In the Java client, write code to instantiate a
LoginContext
. TheLoginContext
consults the configuration file,sample_jaas.config
, to load the default LoginModule configured for WebLogic Server. See the following sampleLoginContext
instantiation.... import javax.security.auth.login.LoginContext; ... LoginContext loginContext = null; try { // Create LoginContext; specify username/password login module loginContext = new LoginContext("Sample", new SampleCallbackHandler(username, password, url)); }
Note:
If you use another means to authenticate the user, such as an Identity Assertion provider or a remote instance of WebLogic Server, the default LoginModule is determined by the remote source.
-
Invoke the
login()
method of theLoginContext
instance. Thelogin()
method invokes all the loaded LoginModules. Each LoginModule attempts to authenticate the subject. If the configured login conditions are not met, theLoginContext
throws aLoginException
. See the following example of thelogin()
method.... import javax.security.auth.login.LoginContext; import javax.security.auth.login.LoginException; import javax.security.auth.login.FailedLoginException; import javax.security.auth.login.AccountExpiredException; import javax.security.auth.login.CredentialExpiredException; ... /** * Attempt authentication */ try { // If we return without an exception, authentication succeeded loginContext.login(); } catch(FailedLoginException fle) { System.out.println("Authentication Failed, " + fle.getMessage()); System.exit(-1); } catch(AccountExpiredException aee) { System.out.println("Authentication Failed: Account Expired"); System.exit(-1); } catch(CredentialExpiredException cee) { System.out.println("Authentication Failed: Credentials Expired"); System.exit(-1); } catch(Exception e) { System.out.println("Authentication Failed: Unexpected Exception, " + e.getMessage()); e.printStackTrace(); System.exit(-1); }
-
Write code in the Java client to retrieve the authenticated Subject from the
LoginContext
instance using thejavax.security.auth.Subject.getSubject()
method and call the action as the Subject. Upon successful authentication of a Subject, access controls can be placed upon that Subject by invoking theweblogic.security.Security
.runAs()
method. TherunAs()
method associates the specified Subject with the current thread's access permissions and then executes the action. See the following example implementation of thegetSubject()
andrunAs()
methods.... /** * Retrieve authenticated subject, perform SampleAction as Subject */ Subject subject = loginContext.getSubject(); SampleAction sampleAction = new SampleAction(url); Security.runAs(subject, sampleAction); System.exit(0); ...
Note:
Use of the JAAS javax.security.auth.Subject.doAs methods in WebLogic Server applications do not associate the Subject with the client actions. You can use the doAs methods to implement Java EE security in WebLogic Server applications, but such usage is independent of the need to use the Security.runAs() method.
-
Write code to execute an action if the Subject has the required privileges. Oracle provides a sample implementation,
SampleAction
, of thejavax.security.PrivilegedAction
class that executes an EJB to trade stocks. TheSampleAction.java
code is available as part of the distribution in the directoryEXAMPLES_HOME
\src\examples\security\jaas
, whereEXAMPLES_HOME
represents the directory in which the WebLogic Server code examples are configured, and can be found atORACLE_HOME
\wlserver\samples\server
. -
Invoke the
logout()
method of theLoginContext
instance. Thelogout()
method closes the user's session and clear theSubject
. See the following example of thelogin()
method.... import javax.security.auth.login.LoginContext; ... try { System.out.println("logging out..."); loginContext.logout(); }
Note:
The LoginModule.logout() method is never called for a WebLogic Authentication provider or a custom Authentication provider, because once the Principals are created and placed into a Subject, the WebLogic Security Framework no longer controls the lifecycle of the Subject. Therefore, code that creates the JAAS LoginContext to log in and obtain the Subject should also call the LoginContext to log out. Calling LoginContext.logout() results in the clearing of the Principals from the Subject.
Using JNDI Authentication
Java clients use the Java Naming and Directory Interface (JNDI) to pass credentials to WebLogic Server. To do this, a Java client establishes a connection with Oracle WebLogic Server by getting a JNDI InitialContext
.and uses InitialContext
to look up the resources it needs in the Oracle WebLogic Server JNDI tree.
.
Note:
JAAS is the preferred method of authentication, however, the WebLogic Authentication provider's LoginModule supports only user name and password authentication. Thus, for client certificate authentication (also referred to as two-way SSL authentication), you should use JNDI. To use JAAS for client certificate authentication, you must write a custom Authentication provider whose LoginModule does certificate authentication. For information on how to write LoginModules, see http://docs.oracle.com/javase/8/docs/technotes/guides/security/jaas/JAASLMDevGuide.html
.
To specify a user and the user's credentials, set the JNDI properties listed in Table 3-1.
Table 3-3 JNDI Properties for Authentication
Property | Meaning |
---|---|
INITIAL_CONTEXT_FACTORY |
Provides an entry point into the Oracle WebLogic Server environment. The class weblogic.jndi.WLInitialContextFactory is the JNDI SPI for Oracle WebLogic Server. |
PROVIDER_URL |
Specifies the host and port of the WebLogic Server that provides the name service. For example: |
SECURITY_PRINCIPAL |
Specifies the identity of the user when that user authenticates to the default (active) security realm. |
SECURITY_CREDENTIALS |
Specifies the credentials of the user when that user authenticates to the default (active) security realm. |
These properties are stored in a hash table that is passed to the InitialContext
constructor. Example 3-2 illustrates how to use JNDI authentication in a Java client running on WebLogic Server.
Note:
For information on JNDI contexts and threads and how to avoid potential JNDI context problems, see JNDI Contexts and Threads and How to Avoid Potential JNDI Context Problems in Developing JNDI Applications for Oracle WebLogic Server.
In versions of WebLogic Server prior to 9.0, when using protocols other than IIOP with JNDI, the first user is "sticky" in the sense that it becomes the default user when no other user is present. This is not a good practice, as any subsequent logins that do not have a username and credential are granted the identify of the default user.
In version 9.0, this is no longer true and there is no default user.
To return to the previous behavior, the weblogic.jndi.WLContext.ENABLE_DEFAULT_USER
field must be set, either via the command line or through the InitialContext interface.
Example 3-2 Example of Authentication
... Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory"); env.put(Context.PROVIDER_URL, "t3://weblogic:7001"); env.put(Context.SECURITY_PRINCIPAL, "javaclient"); env.put(Context.SECURITY_CREDENTIALS, "javaclientpassword"); ctx = new InitialContext(env);
Java Client JAAS Authentication Code Examples
EXAMPLES_HOME
\src\examples\security\jaas
, where EXAMPLES_HOME
represents the directory in which the WebLogic Server code examples are configured and can be found at ORACLE_HOME
\wlserver\samples\server
. For a description of the sample and instructions on how to build, configure, and run this sample, see the package.html
file in the sample directory. You can modify this code example and reuse it.