12 Using the Java EE Security API

The Java EE Security API (JSR 375) defines portable, plug-in interfaces for HTTP authentication and identity stores, and an injectable SecurityContext interface that provides an API for programmatic security. You can use the built-in implementations of the plug-in SPIs, or write custom implementations.

Using the Java EE Security API, you can define all of the security information directly within the application. Bundling the security configuration in the application instead of configuring it externally improves the management of the application’s lifecycle, especially in a world of Docker-hosted microservices that are distributed in containers.

Overview of the Java EE Security API in WebLogic Server

Oracle WebLogic Server supports the Java EE Security API (JSR 375) which defines portable authentication mechanisms (such as HttpAuthenticationMechanism and IdentityStore), and an an access point for programmatic security using the SecurityContext interface. In WebLogic Server, these authentication mechanisms are supported in the web container, and the SecurityContext interfaces are supported in the Servlet and EJB containers.

The programming model for the Java EE Security API 1.0 (JSR 375) is defined in the specification at https://www.jcp.org/en/jsr/detail?id=375. WebLogic Server supports the plug-in interface for authentication, HttpAuthenticationMechanism, and includes built-in support for the BASIC, FORM, and Custom FORM authentication mechanisms defined in the specification. WebLogic Server also supports the RememberMeIdentityStore interface, and built-in implementations of the IdentityStore interface (LDAP identity store and Database identity store) as well as the custom identity store.

The SecurityContext interfaces for web applications and EJBs are described in Authenticating Users Programmatically and Using Programmatic Security With EJBs, respectively.

The HttpAuthenticationMechanism interface is designed to capitalize on the strengths of existing Servlet and JASPIC authentication mechanisms. An HttpAuthenticationMechanism is a CDI bean, and is therefore made available to the container automatically by CDI (see Using Contexts and Dependency Injection for the Java EE Platform in Developing Applications for Oracle WebLogic Server for more information on CDI support). The container is responsible for placing the HttpAuthenticationMechanism into service. The IdentityStore interface is intended primarily for use by HttpAuthenticationMechanism implementations, but could in theory be used by other types of authentication mechanisms (such as a JASPIC ServerAuthModule). HttpAuthenticationMechanism implementations are not required to use IdentityStore — they can authenticate users in any manner they choose — but the IdentityStore interface is a useful and convenient mechanism.

A significant advantage of using the HttpAuthenticationMechanism and IdentityStore interfaces over the declarative mechanisms defined by the Servlet specification is that they allow an application to control the identity stores that it authenticates against in a standard, portable way. Because implementations of these SPI interfaces are CDI beans, applications can provide implementations that support application-specific authentication mechanisms, or validate user credentials against application-specific identity stores, simply by including them in a bean archive that is part of the deployed application.

About the HttpAuthenticationMechanism Interface

The HttpAuthenticationMechanism interface defines an SPI for writing authentication mechanisms that can be provided with an application and deployed using CDI. Developers can write their own implementations of HttpAuthenticationMechanism to support specific authentication token types or protocols. There are also several built-in authentication mechanisms that perform BASIC, FORM, and Custom FORM authentication.

The built-in authentication mechanisms are enabled and configured using annotations that, when used, make the corresponding built-in mechanism available as a CDI bean. The Java EE Security API also supports the use of Expression Language 3.0 in these annotations to allow dynamic configuration. For more information about Java Expression Language (EL), see the JSR-000341 Expression Language 3.0 specification at https://jcp.org/en/jsr/detail?id=341.The annotations for the built-in authentication mechanisms are as follows:

  • BasicAuthenticationMechanismDefinition — implements BASIC authentication that conforms to the behavior of the servlet container when BASIC <auth-method> is declared in web.xml. In BASIC authentication, the web client obtains the user name and the password from the user and transmits them to the web server. The web server then authenticates the user in the specified realm.

  • FormAuthenticationMechanismDefinition — implements FORM authentication that conforms to the behavior of the servlet container when the FORM <auth-method> is declared in web.xml. FORM Based Authentication introduces a required form-based authentication mechanism that allows a developer to control the look and feel of the login screens. The web application deployment descriptor contains entries for a login form and error page. The login form must contain fields for entering a user name and password.

  • CustomFormAuthenticationMechanismDefinition — implements a modified version of FORM authentication. In WebLogic Server, the difference is that authentication occurs by invoking SecurityContext.authenticate() using the credentials the application collected.

An implementation of HttpAuthenticationMechanism must be a CDI bean to be recognized and deployed at runtime, and is assumed to be application scoped. During bean discovery, the servlet container looks for a bean that implements HttpAuthenticationMechanism — there should be only one per application — and, if found, arranges for it to be deployed to authenticate the application’s callers.

The servlet container leverages JASPIC, the Java Authentication Service Provider Interface for Containers, to deploy authentication mechanisms. The container provides a JASPIC Server Auth Module (SAM) that can delegate to an HttpAuthenticationMechanism, and arranges for that "bridge" SAM to be registered with the JASPIC AuthConfigFactory. At runtime, normal JASPIC processing invokes the bridge SAM, which then delegates to the HttpAuthenticationMechanism to perform the authentication and drive any necessary dialog with the caller, or with third parties involved in the authentication protocol flow.

HttpAuthenticationMechanism Interface Methods

The HttpAuthenticationMechanism interface defines three interface methods, which correspond to the three methods defined by the JASPIC ServerAuth interface.

When one of the JASPIC methods is invoked on the bridge SAM, it delegates to the corresponding method of the HttpAuthenticationMechanism. Although the method names are identical, the method signatures are not; the bridge SAM maps back and forth between the parameters passed to it by the JASPIC framework, and the parameters expected by an HttpAuthenticationMechanism.

The three HttpAuthenticationMechanism interface methods are as follows:

  • validateRequest() — validate an incoming request and authenticate the caller.

  • secureResponse() — secure a response message. This method is  optional if the default is sufficient.

  • cleanSubject() — clear the provided Subject of principals and credentials. This method is  optional if the default is sufficient.

Only the validateRequest() method must be implemented by an HttpAuthenticationMechanism; the interface includes default implementations for secureResponse() and cleanSubject() that will often be sufficient.

HttpAuthenticationMechanism Interface Annotations

You can use the following annotations to add additional behaviors to an HttpAuthenticationMechanism:

  • AutoApplySession — provides an application with a way to declaratively enable JASPIC javax.servlet.http.registerSession behavior for an authentication mechanism, and automatically apply it for every request.

  • LoginToContinue — provides an application with the ability to declaratively add "login to continue" functionality to an authentication mechanism. The annotation is also used to configure the login page, error page, and redirect/forward behavior for the built-in form-based authentication mechanisms.

  • RememberMe - specifies that a RememberMe identity store should be used to enable RememberMe functionality for the authentication mechanism. To use RememberMe, the application must provide its implementation of HAM and annotate the HAM with the RememberMe annotation.

About the Identity Store Interfaces

In WebLogic Server, all built-in authentication mechanisms need to be authenticated using an identity store. The Java EE Security API defines two identity store interfaces, IdentityStore and RememberMeIdentityStore. The IdentityStore interface defines methods for validating a caller's credentials, such as username and password, and returning group membership information. The RememberMeIdentityStore interface is a variation on the IdentityStore interface intended specifically to address cases where the identity of an authenticated user should be remembered for an extended period of time.

The following topics describe the identity store interfaces in more detail:

IdentityStore Interface

The IdentityStore interface defines an SPI for interacting with identity stores, which are directories or databases containing user account information. An implementation of the IdentityStore interface can validate users' credentials, provide information about the groups they belong to, or both. Most often, an IdentityStore implementation will interact with an external identity store — an LDAP server, for example — to perform the actual credential validation and group lookups, but an IdentityStore may also manage user account data itself.

There are two built-in implementations of IdentityStore: an LDAP identity store, and a Database identity store. These identity stores delegate to external stores that must already exist; the IdentityStore implementations do not provide or manage the external store. Use the following annotations to configure communication between the IdentityStore interface and an external store:

  • LdapIdentityStoreDefinition — configures an identity store with the parameters necessary to communicate with an external LDAP server, validate user credentials, and/or lookup user groups.

  • DatabaseIdentityStoreDefinition — configures an identity store with the parameters necessary to connect to an external database, validate user credentials, and/or lookup user groups. You must supply a PasswordHash implementation when configuring a Database Identity Store.

An application can provide its own custom identity store, or use the built-in LDAP or database identity stores. An optional example demonstrating the use of a built-in database identity store is included with your WebLogic Server installation. The example is located in the EXAMPLES_HOME\examples\src\examples\javaee8\security directory, where EXAMPLES_HOME represents the directory in which the WebLogic Server code examples are configured. By default, this directory is 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.

An implementation of IdentityStore must be a CDI bean to be recognized and deployed at runtime, and is assumed to be application scoped. Multiple implementations of IdentityStore may be present. If so, they are invoked under the control of an IdentityStoreHandler.

IdentityStoreHandler

Authentication mechanisms do not interact with IdentityStore directly; instead, they call an IdentityStoreHandler. An implementation of the IdentityStoreHandler interface provides a single method, validate(Credential), which, when invoked, iterates over the available IdentityStores and returns an aggregated result. An IdentityStoreHandler must also be a CDI bean, and is assumed to be application scoped. At runtime, an authentication mechanism injects the IdentityStoreHandler and invokes on it. The IdentityStoreHandler, in turn, looks up the available IdentityStores and invokes on them to determine the aggregate result.

There is a built-in IdentityStoreHandler that implements a standard algorithm defined by the Java EE Security API specification. An application may also supply its own IdentityStoreHandler, which can use any desired algorithm to select and invoke on IdentityStores, and return an aggregated (or non-aggregated) result.

IdentityStore Interface Methods

The IdentityStore interface has four methods:

  • validate(Credential) — validate a Credential, and return the result of that validation.

  • getCallerGroups(CredentialValidationResult) — return the groups associated with the caller indicated by the supplied CredentialValidationResult, which represents the result of a previous, successful validation.

  • validationTypes() — returns a Set of validation types (one or more of VALIDATE, PROVIDE_GROUPS) that indicate the operations supported by this instance of the IdentityStore.

  • priority() — returns a positive integer representing the self-declared priority of this IdentityStore. Lower values represent higher priority.

Because getCallerGroups() is a sensitive operation — it can return information about arbitrary users, and does not require that the caller provide the user’s credential or proof of identity — the caller should have the IdentityStorePermission("getGroups") permission. For this permission check to be performed, ensure that the Java Security Manager is enabled. See Using the Java Security Manager to Protect WebLogic Resources.

RememberMeIdentityStore Interface

The RememberMeIdentityStore interface represents a special type of identity store. It is not directly related to the IdentityStore interface; that is, it does not implement or extend it. It does, however, perform a similar, albeit specialized, function. You use the RememberMeIdentityStore interface when an application wants to "remember" a user’s authenticated session for an extended period, so that the caller can return to the application periodically without needing to present primary authentication credentials each time. For example, a web site may remember you when you visit, and prompt for your password only periodically, perhaps once every two weeks, as long as you don’t explicitly log out.

RememberMe works as follows:

  • When a request from an unauthenicated user is received, the user is authenticated using an HttpAuthenticationMechanism that is provided by the application (this is required — RememberMeIdentityStore can only be used in conjunction with an application-supplied HttpAuthenticationMechanism).

  • After authentication, the configured RememberMeIdentityStore saves information about the user’s authenticated identity, so that it can be restored later, and generates a long-lived "remember me" login token that is sent back to the client, perhaps as a cookie.

  • On a subsequent visit to the application, the client presents the login token. The RememberMeIdentityStore then validates the token and returns the stored user identity, which is then established as the user’s authenticated identity. If the token is invalid or expired, it is discarded, the user is authenticated normally again, and a new login token is generated.

The RememberMeIdentityStore interface defines the following methods:

  • generateLoginToken(CallerPrincipal caller, Set<String> groups) — generate a login token for a newly authenticated user, and associate it with the provided caller/group information.

  • removeLoginToken(String token) — remove the (presumably expired or invalid) login token and any associated caller/group information.

  • validate(RememberMeCredential credential) — validate the supplied credential, and, if valid, return the associated caller/group information. (RememberMeCredential is essentially just a holder for a login token).

An implementation of RememberMeIdentityStore must be a CDI bean, and is assumed to be application scoped. You configure a RememberMeIdentityStore by adding a RememberMe annotation to an application’s HttpAuthenticationMechanism, which indicates that a RememberMeIdentityStore is in use, and provides related configuration parameters. A container-supplied interceptor then intercepts calls to the HttpAuthenticationMechanism, invokes the RememberMeIdentityStore as necessary before and after calls to the authentication mechanism, and ensures that the user’s identity is correctly set for the session. The Java EE Security API specification (JSR 375) (https://jcp.org/en/jsr/detail?id=375) provides a detailed description of the required interceptor behavior.

Implementations of RememberMeIdentityStore should take care to manage tokens and user identity information securely. For example, login tokens should not contain sensitive user information, like credentials or sensitive attributes, to avoid exposing that information if an attacker were able to gain access to the token — even an encrypted token is potentially vulnerable to an attacker with sufficient time/resources. Similarly, tokens should be encrypted/signed wherever possible, and sent only over secure channels (HTTPS). User identity information managed by a RememberMeIdentityStore should be stored as securely as possible (but does not necessarily need to be reliably persisted — the only impact of a "forgotten" session is that the user will be prompted to log in again).

Usage Requirements

Using the Java EE Security API authentication mechanisms does not require any specific configuration, but you must ensure that other functionality, such as JASPIC and CDI, is enabled.

To use the Java EE Security API features in WebLogic Server, note the following requirements:

  • Web applications must include the beans.xml deployment descriptor file in the application's WAR or EAR file, as specified by the CDI specification. Because the HttpAuthenticationMechanism and IdentityStore interfaces are implemented as CDI beans, they are visible to the container through CDI.

  • The metadata-complete attribute in the web.xml file for the web applications must NOT be set to true. The default in WebLogic Server is false.

  • JASPIC must be enabled at the domain level. By default, JASPIC is enabled for a domain in WebLogic Server.