Skip to main content

Security is a major component of application development. Jakarta EE provides the robust Jakarta Security specification that when paired with the Jakarta Authentication and Jakarta Authorization specifications, provides APIs that deliver end-to-end security. There are a large number of application processes that require security measures, and these specifications provide the ability to do so in a straightforward manner using annotations and minimal XML configurations. Jakarta EE compliant containers and deployment environments adhere to the constructs of the Authentication and Authorization policies to ensure that applications can be secured in a standard way and deployed across a number of different environments.

Overview of Application Security

Applications consist of both protected and unprotected resources, and application security is involved with protected resources. With respect to web applications, security begins when the initial request is made to the main application URL, at which point the application container determines whether the client is authorized access to the resource. Part of this initial process is to also determine whether the client is required to be authenticated to visit the requested URL, and if so, an authentication process needs to occur. Authentication requires some type of credential from the client, oftentimes a username/password, or perhaps a JWT Token, and this credential then needs to be validated.

Once the credential has been validated, the application container then consults a security policy to determine if the client has authorization to access the requested resource. The security policy outlines different roles required to access the resource, and the validation process attempts to map the user to one of the roles which has access.

Each of the steps outlined thus far are required for front end security, providing access to requested resources. There are also security mechanisms required to protect business methods in a similar manner. Jakarta Security contains APIs for securing the entire application. Given this explanation, the following sections provide an overview of what role these specifications play in the process.

Configuration for Jakarta Security

Jakarta Security is part of any container that is compatible with the Jakarta EE Platform. However, to explicitly add the Jakarta Security API to a maven application, add the following dependency:

<dependency>
    <groupId>jakarta.security.enterprise</groupId>
    <artifactId>jakarta.security.enterprise-api</artifactId>
    <version>3.0.0</version>
</dependency>

Along with an implementation:
<dependency>
    <groupId>org.glassfish.soteria</groupId>
    <artifactId>jakarta.security.enterprise</artifactId>
    <version>3.0.0</version>
</dependency>

Jakarta Security

The Jakarta Security specification provides a standard means for securing Jakarta EE applications through the use of Authentication mechanisms. The mechanisms provide implementations for the HttpAuthenticationMechanism interface, which are used to specify how a user is authenticated, and whether an authenticated user gains access to a requested resource. The HttpAuthenticationMechanism interface enables developers to work with code configuring through annotations, rather than XML. Jakarta Security enables security for each of the authentication methods that are defined by the Servlet specification by providing authentication mechanisms for each:

  • Basic HTTP: When the BasicAuthenticationMechanismDefinition annotation is applied, if an unauthorized request is received, the container will negotiate with the client to achieve authorization.
  • Form-Based: The FormAuthenticationMechanismDefinition provides options for specifying a login page and an error page. When the login page is specified, the server will send the standard login form to the client, which will then send the form contents through authentication business logic.
  • Custom Form: The CustomFormAuthenticationMechanism annotation allows one to specify a login page just like the form-based authentication, but a custom login page incorporating logic which invokes the SecurityContext is used. The SecurityContext enables a custom authentication implementation to be applied.
  • OpenID Connect: The OpenIdAuthenticationMechanismDefinition annotation authenticates according to the Authorization Code flow and Refresh tokens, as defined by the OpenID Connect specification. The mechanism requires metadata about the OpenID Connect Provider to function properly.

It should be noted that custom authentication mechanisms can be developed by implementing the HttpAuthenticationMechanism interface. This interface defines methods which align with those contained within the Jakarta Authentication ServerAuth interface to ensure that a caller is properly authenticated and authorized to access a requested resource.

  • validateRequest (required): Provided to allow a caller to authenticate to a resource.
  • secureResponse: Provided to allow post processing to occur on the response generated by a servlet and/or servlet filter.
  • cleanSubject: Provided to allow for cleanup after logout.

Authentication mechanisms are configured by placing an annotation respective to the desired type of authentication, onto a Jakarta CDI bean. For instance, to apply Basic authentication, the following annotation can be placed on an ApplicationScoped Jakarta CDI bean.

@BasicAuthenticationMechanismDefinition(
    realmName = "myRealm")
@ApplicationScoped
public class MyClass {}

In a similar manner, form based authentication can be configured using the following. In this case, the @LoginToContinue method redirects the user to the login screen or to an error page if the login attempt is unsuccessful.

@FormAuthenticationMechanismDefinition (
    loginToContinue = @LoginToContinue (
        loginPage = "/authenticate.html",
        errorPage = "/loginError.html"))
@ApplicationScoped
public class MyClass {}

Jakarta Security defines an IdentityStore API which can be used to communicate with Identity Stores used to authenticate a user and obtain a user’s defined roles. Default identity stores are provided by the compliant container for database and LDAP authentication using the @DatabaseIdentityStoreDefinition or @LdapIdentityStoreDefinition, respectively. It is also possible to create a custom Identity store by implementing the IdentityStore interface. For instance, to configure an LDAP identity store, one may do the following:

@LdapIdentityStoreDefinition(
    url = "ldap://myserver:port",
    callerBaseDn = "ou=caller,dc=example,dc=org",
    gropuSearchBase = "ou=group,dc=example,dc=org",
    groupSearchFilter = "")
@ApplicationScoped
public class MyClass {}

The SecurityContext provides an elegant way to programmatically work with security APIs via a Jakarta CDI bean. The SecurityContext interface is available at runtime, so it can be injected and utilized to do things such as authenticate a user, check role membership, and more.

Jakarta Authentication

Jakarta Authentication is integrated into Jakarta Security as a low level Service Provider Implementation (SPI) for authentication mechanisms. Mentioned in the previous section, authentication mechanisms are controllers that interact with a caller and a container’s environment to obtain the caller’s credentials, validate the credentials, and pass an authenticated identity to the container. Jakarta Authentication consists of several profiles, with each telling how a specific container can integrate with and adapt to this SPI.

  • Servlet Container Lite Profile
  • REST Profile
  • SOAP Profile

The authentication specification covers a wide focus on client and server authentication. An authentication context is responsible for constructing, initializing, and coordinating the invocation of one or more encapsulated authentication modules. At a high level, a typical authentication process flow works as follows:

  1. Client sends a secure request to the server
  2. Server validates the request
  3. Server dispatches request to service and sends back a secure response
  4. Client validates the response

Request and response messages are implementations of a MessageInfo interface. Typically, a runtime would perform the following steps to secure or validate a message. Steps 1-4 below are performed one time, while 5 is repeated for each message.

  1. Acquire AuthConfigProvider, which is used for obtaining an authentication configuration for relevant messaging layer and application identifier.
  2. Acquire AuthConfig from the provider: a) ClientAuthConfig: Client configuration b) ServerAuthConfig: Server configuration
  3. Acquire AuthContext Identifier for client or server from the corresponding AuthConfig.
  4. Acquire Authentication Context which will be used to process identified messages.
    a) ClientAuthContext: Client context b) ServerAuthContext: Server Context
  5. Process Messages

An authentication module is invoked to validate a message, and it is passed a Subject object to receive the credentials of the source of the message and a separate Subject object to represent the credentials of the recipient of the message. The authentication modules contexts return AuthStatus values with the status, and AuthExceptions if an exception occurs. It should be noted that there can be more than one authentication module, and these can be invoked independently and concurrently.

Jakarta Authorization

Jakarta Authorization is another integral specification that goes hand in hand with Jakarta Security. It consists of a low-level SPI for authorization policy modules, which are repositories of permissions which determine whether a subject has a given permissions to access a requested resource. This specification defines a contract between containers and authorization policy modules, which provides authorization functionality to suit the operational environment. The contract is divided into three subcontracts, which together, describe the installation and configuration of the authorization providers.

  • Provider Configuration Subcontract: Defines requirements placed on providers and containers such that Policy providers may be integrated with containers.
  • Policy Configuration Subcontract: Defines interactions between container deployment tools and providers to support translation of authorization policies into policy statements within a Java SE Policy provider.
  • Policy Decision and Enforcement Subcontract: Defines the interactions between container policy enforcement points and providers that implement policy decisions that are required by containers.

Jakarta Authorization provides a standard means for working within the boundaries of each of the three subcontracts. The Policy Configuration Subcontract works along with the standard java.security.Policy to provide standard policies for a container. It also provides a means of configuring policies using policy providers, such that the policy can be changed to reflect what is needed for the specific environment. Jakarta Authorization also provides a means for configuring security groups, roles, and constraints for restricting access to particular pages within an application. The Policy Configuration Subcontract specifies a means for ensuring that the container will adhere to a standard method for specifying such roles and permissions. Lastly, the Policy Decision and Enforcement Subcontract ensures that policies are enforced in a standard way across Jakarta Servlets and Jakarta Enterprise Beans.

Conclusion

Jakarta Security, Jakarta Authentication, and Jakarta Authorization specifications together provide robust security standards that can be applied to Jakarta EE applications. Since these specifications are standards across all compliant containers, developers can implement security that can be easily maintained or modified, as needed. Jakarta Security provides a means for declaratively specifying authentication types, identity stores, and for working with the API, rather than using XML. Along with Authentication and Authorization, Jakarta Security provides the tools and APIs to properly secure applications.

Back to the top