Enterprise Java

Java EE 8 Security API: Overview

The New Security API

Probably, the single most significant new feature added to Java EE 8 is the new security API.

The primary motivations for this new API were to simplify, standardize and modernize the way security concerns are handled across containers and implementations. And they have done a great job.

  • The configuration of web authentication has been modernized thanks to three new annotations that make web.xml file declaration redundant.
  • The new Security Context API standardizes the way the servlet and EJB container perform authentication and
  • The new Identity Store abstraction to simplifies the use of identity stores.

For now, let’s look at the first of these new features.

Annotation-Driven Authentication Mechanism

This feature is all about configuring web security. Which traditional required XML declaration in the web.xml file.

This is no longer necessary, thanks to the HttpAuthenticationMechanism interface which represents an HTTP authentication and comes with three built-in CDI-enabled implementations each representing one of the three ways web security can be configured.

They are trigger with the use of one of these annotations.

@BasicAuthenticationMechanismDefinition
@FormAuthenticationMechanismDefinition
@CustomFormAuthenticationMechanismDefinition

They replicate the functionality of the classic HTTP basic authentication, form and custom form based authentication already available in the servlet container.

For example, to enable Basic authentication all that is necessary is to add the BasicAuthenticationMechanismDefinition annotation to your servlet and that’s it.

@BasicAuthenticationMechanismDefinition(realmName="${'user-realm'}")
@WebServlet("/user")
@DeclareRoles({ "admin", "user", "demo" })
@ServletSecurity(@HttpConstraint(rolesAllowed = "user"))
public class UserServlet extends HttpServlet { … }

You can now throw away your XML configurations and use one of these new annotations to drive web security.

The next great feature of the security API is the Identity store abstraction.

Identity Store Abstraction

An identity store is a database that stores user identification data such as user name, group membership, and information used to verify credentials.

The new Java EE Security API provides an identity store abstraction called IdentityStore which is used to interact with identity stores in order to authenticate users and retrieve group memberships and is akin to the JAAS LoginModule interface.

It is intended that IdentityStore is used by HttpAuthenticationMechanism implementations, although that isn’t a requirement. The IdentityStore can stand separate and be used by any other authentication mechanism the application developer wishes.

Nevertheless, the use of IdentityStore and HttpAuthenticationMechanism together enables an application to control the identity stores it uses for authentication in a portable and standard way and is the recommended way for most use case scenarios.

Now, you are enabled to implement your own identity store by implementing the IdentityStore interface or you can use one of the built-in IdentityStore implementations for LDAP and relational databases. They are initialized by passing configuration details to the appropriate annotation @LdapIdentityStoreDefinition or @DataBaseIdentityStoreDefinition.

Let’s have a look a the use of a built-in identity store.

The simplest identity store is the database store. It is configured via the @DataBaseIdentityStoreDefinition annotation as shown below.

@DatabaseIdentityStoreDefinition(
  dataSourceLookup = "${'java:global/permissions_db'}",
  callerQuery = "#{'select password from caller where name = ?'}",
  groupsQuery = 
     "select group_name from caller_groups where caller_name = ?",
  hashAlgorithm = PasswordHash.class,
  priority = 10
)
@ApplicationScoped
@Named
public class ApplicationConfig { ... }

The configuration options are fairly self-explanatory and should be familiar to you if you have configured a database definition.

However, note the priority set to 10, this is used in case multiple identity stores are found by the runtime and determines the iteration order relative to other stores. Lower numbers have higher priority.

Now let’s take a look that the final new feature of the security API.

The Security Context

The goal of the security context is to provide consistent access to security context across the servlet and EJB containers.

Currently, these containers implement security context objects inconsistently. For example, the servlet container provides an HttpServletRequest instance on which the getUserPrincipal() method is called to obtain the user Principal, and the EJB container provides the differently named EJBContext instance, on which the same named method is called. And likewise, to test if the user belongs to a certain role the method isUserRole() is called on the HttpServletRequest instance and the isCallerInRole() is called on the EJBContext instance.

The SecurityContext provides consistency across the Servlet and EJB container for obtaining this kind of information. It has five methods and none of which have default implementations.

Principal getCallerPrincipal(); Returns the platform-specific principal representing the name of the current authenticated user or null if the current caller is not authenticated.

<T extends Principal> Set<T> getPrincipalsByType(Class<T> pType); Returns all Principals of the given type from the authenticated caller’s Subject, otherwise, an empty Set is returned if neither the pType type is found or the current user is not authenticated.

boolean isCallerInRole(String role); Determines whether or not the caller is included in the specified role otherwise it returns false if the user is not authorized.

boolean hasAccessToWebResource(String resource, String… methods); Determines whether or not the caller has access to the given web resource via the methods provided.

AuthenticationStatus authenticate(HttpServletRequest req, HttpServletResponse res, AuthenticationParameters param); Informs the container that it should start or continue an HTTP based authentication conversation with the caller. This method only works in the servlet container because of its dependence on the HttpServletRequest and HttpServletResponse instances.

The security context is a CDI bean and therefore injectable into any class in the servlet and EJB container.

@Inject
private SecurityContext securityContext;

With the SecurityContext instance in hand, you can call any of the methods to get access to context-aware security information.

boolean hasAccess = securityContext  
    .hasAccessToWebResource("/secretServlet", "GET");

Now that wraps up this overview of the security API, there is plenty more to know about the Security API.

Published on Java Code Geeks with permission by Alex Theedom, partner at our JCG program. See the original article here: Java EE 8 Security API: Overview

Opinions expressed by Java Code Geeks contributors are their own.

Alex Theedom

Alex Theedom is a Senior Java Developer and has recently played a pivotal role in the architectural design and development of a microservice based, custom built lottery and instant win game platform. Alex has experience of Java web application development in a diverse range of fields including finance, e-learning, lottery and software development. He is the co-author of Professional Java EE Design Patterns and many articles.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button