11 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 whenBASIC <auth-method>
is declared inweb.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 theFORM <auth-method>
is declared inweb.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 invokingSecurityContext.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 JASPICjavax.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 aRememberMe
identity store should be used to enableRememberMe
functionality for the authentication mechanism. To useRememberMe
, the application must provide its implementation of HAM and annotate the HAM with theRememberMe
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 aPasswordHash
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 suppliedCredentialValidationResult
, which represents the result of a previous, successful validation. -
validationTypes()
— returns a Set of validation types (one or more ofVALIDATE
,PROVIDE_GROUPS
) that indicate the operations supported by this instance of theIdentityStore
. -
priority()
— returns a positive integer representing the self-declared priority of thisIdentityStore
. 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-suppliedHttpAuthenticationMechanism
). -
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 theHttpAuthenticationMechanism
andIdentityStore
interfaces are implemented as CDI beans, they are visible to the container through CDI. -
The
metadata-complete
attribute in theweb.xml
file for the web applications must NOT be set totrue
. The default in WebLogic Server isfalse
. -
JASPIC must be enabled at the domain level. By default, JASPIC is enabled for a domain in WebLogic Server.