BACKGROUND IMAGE: iSTOCK/GETTY IMAGES
When leafing through the pages of the recently ratified JSR-375, the new Java EE Security API, it's amusing how quickly the reading of the spec turns into an exercise of uttering to yourself, "Seriously, have they not standardized this stuff yet?"
Historically, implementing various aspects of Java EE security was a responsibility shouldered primarily by the application server vendor, and hooking into those proprietary systems was always a headache. Any software architect who has gone through the process of setting up a WebSphere cluster, configuring a WebLogic server or doing a Liferay installation has inevitably wasted time jumping through the odious hoops that were required to connect to a proprietary user attribute registry or third-party authentication store. For those unlucky enough not to have a simple LDAP server that provided this functionality, a custom user registry might have to be developed, which meant coding against a vendor-specific API and hooking that into the application server's runtime.
These little Java EE security nuisances were never show stoppers. There have always been workarounds or third-party frameworks that would help an organization achieve their security goals. The problem was that these various approaches weren't standardized. And while there are many aspects of Java EE security that are documented within specifications, much of which can be found in the often overlooked Java Authentication Service Provider Interface for Containers (JASPIC) specification. Unfortunately, JASPIC isn't fun to work with. Furthermore, it isn't annotation-based and it doesn't leverage container-based dependency injection. JSR-375, the Java EE Security API, is an attempt to address these security-related issues.
Containers, microservices and Java EE security
"It's an important specification because it bridges some of the gaps that existed in previous Java EE versions," said Java Champion Ivar Grimstad, who is hosting a JavaOne 2017 session entitled, "New Security APIs for Java EE." "Now it's there, and that's a good thing. It's a good foundation on which to build upon so if you want OAUTH or support for microservices, you have a good foundation to build upon."
But perhaps the most significant aspect of the JSR-375 API is the fact that it allows for all of the security information to be defined within the application, and not configured externally. "You do it all in the application," Grimstad said. "You don't need to configure it from the outside."
That's a significant improvement in managing the lifecycle of an application, especially in a world of Docker-hosted microservices that are distributed in containers. "With annotations, you can easily add security and you don't have to do any vendo- specific configuration to get it working."
The annotation based approach to security isn't insignificant.
One of the nice things about JSR-375 is the fact that it doesn't try to boil the ocean on its first run around the block. The enterprise security specification can be broken down into three key parts.
1. The authentication mechanism
Web-based authentication isn't anything new. Every Servlet engine supports basic, digest, form and certificate authentication. But existing APIs don't provide many hooks allowing developers to interact with the process. Doing something as simple as ensuring the authentication happens against a specific user registry isn't possible without digging into non-standard APIs. Furthermore, there is no support for authentication mechanisms other than the aforementioned four. And mechanisms for doing things like firing off callbacks to the application after a user is authenticated don't exist.
Many of these issues are addressed by JASPIC, but JASPIC demands a great deal of coding effort while lacking any declarative support that software developers have come to expect after the release of Java 5. The Java EE Security API's HttpAuthenticationMechanism interface, built in JavaBeans containing sensible defaults and annotations such as @RememberMe and @LoginToContinue, greatly simplifies the act of programmatically interacting with authentication services.
2. The Java EE security identity store
The identity store is a central part of any Java EE security implementation, but a simple and standard mechanism for interacting with it has always been lacking. To simplify and standardize the process, the Java EE Security API defines an IdentityStore interface and a CredentialValidationResult object, both of which work together to perform the simple tasks of validating a user, providing the caller's unique identifier, and the various groups to which a user belongs. Interfaces for interacting with an LDAP-based identity store or a relational database as an identity store are also defined.
3. The Java EE security context
When it comes to writing low-level code to programmatically secure Java resources, the EE specification has always been somewhat lacking. Declarative security is simple to use and always preferred, but it doesn't meet the needs of every application. Enterprise software often has fine-grained security requirements that can only be fulfilled programmatically. That's where the Java EE Security Context comes in.
The Security Context provides familiar methods, such as getCallerPrincipal() and isCallerInRole(String role) that helps to identify who is invoking a given resource. More interesting are methods such as the boolean hasAccessToWebResource method that can determine if a user can invoke a given HTTP method on a Servlet. Another interesting addition is the authenticate() method which programmatically triggers a challenge. Prior to the Java EE Security API, challengers were only triggered when a resource was accessed, and programmatic triggering wasn't possible.
The team that worked on JSR-375 should be proud of their accomplishment. This first version of the Java EE Security API does a good job at standardizing security and addressing many of the shortcomings of the existing Java EE and JASPIC APIs. It is a solid foundation upon which to further build upon and enhance.
The key to cloud native security? Going back to secure coding fundamentals
Learn how the DevSecOps trend is changing Docker and microservices security
Beware: There just might be a hidden security threat embedded in your open source software