The Provider Configuration Subcontract defines the requirements placed on providers and implementations such that Policy providers may be integrated with implementations.
The contract defined by this specification has been designed to work in Jakarta EE 11 or later
Jakarta EE environments with the default jakarta.security.jacc.Policy
implementation class.
An application server that supports this contract must allow replacement of the top level
jakarta.security.jacc.Policy
object used by the application server for all applications running on it,
in addition to supporting a jakarta.security.jacc.Policy
object for individual applications.
This contract defines the package, jakarta.security.jacc
, that contains (among other things) Permission
classes to be used by containers in their access decisions.
A Policy Configuration implementation is the object that holds the Permission instances a Policy can use to make its authorization decisions. The Policy Configuration implementation can be replaced if needed, although for most common uses this should not be needed.
Replacement is done via the jakarta.security.jacc.PolicyConfigurationFactory
abstract factory class. A
default static method, getPolicyConfigurationFactory
is provided that uses the system property
jakarta.security.jacc.PolicyConfigurationFactory.provider
to locate a concrete implementation. The
container can alternatively set a custom PolicyConfigurationFactory
using the
setPolicyConfigurationFactory
method. In that case the PolicyConfigurationFactory
implementation
can come from a container specific configuration, or in case of the Servlet Container
from the context property jakarta.security.jacc.PolicyConfigurationFactory.provider
. If the
PolicyConfigurationFactory
has a public constructor with one argument of type PolicyConfigurationFactory
,
then the container should call this constructor with as argument the PolicyConfigurationFactory
instance
that is being replaced. This allows a replacement PolicyConfigurationFactory
to wrap the existing one
and selectively provide extra functionality.
From this factory class a concrete implementation of the Policy Configuration of type
jakarta.security.jacc.PolicyConfiguration
can be obtained using the method getPolicyConfiguration
.
Use of the PolicyConfiguration
interface is defined in [a232].
This jakarta.security.jacc
package defines a utility class that is used by containers to communicate policy context
identifiers to Policy providers. The utility class is jakarta.security.jacc.PolicyContext
, and this class implements
static methods that are used to communicate policy relevant context values from containers to Policy providers.
Containers use the static method PolicyContext.setContextID
to associate a policy context identifier with a thread
on which they are about to call a decision interface of a Policy provider. Policy providers use the static method
PolicyContext.getContextID
to obtain the context identifier established by a calling container.
The role of policy context identifiers in access decisions is described in [a253].
In addition to the methods used to communicate policy context identifiers, the jakarta.security.jacc.PolicyContext
class also provides static methods that allow container specific context handlers that implement the
jakarta.security.jacc.PolicyContextHandler
interface to be registered with the PolicyContext
class.
The PolicyContext
class also provides static methods that allow Policy
providers to activate registered
handlers to obtain additional policy relevant context to apply in their access decisions.
Use of the PolicyContext
class is defined in [a232].
A jakarta.security.jacc.PrincipalMapper
is an object that maps from a collection of generic Principals
or a Subject
to well known entities in Jakarta EE. A Subject
is a "bag of principles", which can contain any number
of principals, with each principal in that bag representing some attribute of the subject in question. A portable
Policy
does not know which principal represents what entity, as historically no interfaces or annotations have been
standardised to mark them as such.
Using the PrincipalMapper
a given number of well known entities can be retrieved from the Subject
.
The following well known entities are supported:
-
The caller principal - a
java.security.Principal
containing the name of the current authenticated user (if any). -
The role - a
java.lang.String
representing the logical application role associated with the caller principal.
A PrincipalMapper
is intended to be used by a Policy
, but should work outside a Policy
(for instance, during
request processing in a Servlet container).
A Jakarta Authorization implementation can be provided with custom classes that implement the
PolicyConfigurationFactory
class and PolicyConfiguration
interface. These classes can be used by the Policy
implementation class installed for use by the Jakarta Authorization implementation.
In the case where the provider is not seeking to replace the Policy
implementation used by the Jakarta
Authorization implementation, no other components need be provided.
If the provider is seeking to replace the Policy
implementation used by the Jakarta Authorization implementation,
then the Jakarta Authorization implementation must be provided with an environment specific Policy
implementation
class.
A replacement Policy
object must assume responsibility for performing all policy decisions within the entire
application server (in case the Jakarta Authorization implementation is integrated into an application server)
in which it is installed that are requested by way of the Policy
interface that it implements. Alternatively or
additionally a replacement Policy
can be installed for an individual (web) application.
A replacement Policy
object may accomplish this by delegating jakarta.security.jacc
policy decisions to the
corresponding default Policy
implementation class. A replacement Policy
object that fully or partially relies
in this way on the corresponding default Policy
implementation class must identify itself in its installation
instructions as a “delegating Policy provider”.
A Jakarta Authorization implementation must bundle or install the Jakarta Authorization API. This
API consists of all types from the jakarta.security.jacc
package. It must provide default implementations
of its interfaces and abstract classes.
To enable delegation of jakarta.security.jacc
policy decisions to default Policy
providers, all Jakarta Authorization implementations must support the following Policy
replacement algorithm. The intent of the algorithm is to ensure that Policy
objects can capture
the instance of the corresponding default Policy
object during their integration into a container
and such that they may delegate policy evaluations to it.
For each Jakarta EE 11 or later version Jakarta EE compatible implementation, if the system property
"`jakarta.security.jacc.policy.provider`” is defined, the Jakarta Authorization implementation must construct
an instance of the class identified by the system property, confirm that the resulting object is an instance
of jakarta.security.jacc.Policy
, and set, by calling the jakarta.security.jacc.PolicyFactory#setPolicy
method,
the resulting object as the corresponding Policy
object used by the Jakarta Authorization implementation.
For example:
String policyClassName = System.getProperty("jakarta.security.jacc.policy.provider");
if (policyClassName != null) {
try {
Policy policy = loadPolicy(policyClassName);
PolicyFactory.getPolicyFactory().setPolicy(policy);
} catch (Exception e) {
// ...
}
}
private Policy loadPolicy(String policyClassName) throws ReflectiveOperationException, SecurityException {
Object policyInstance =
Thread.currentThread()
.getContextClassLoader()
.loadClass(policyClassName)
.getDeclaredConstructor()
.newInstance();
if (!(policyInstance instanceof Policy)) {
throw new RuntimeException("..."));
}
return (Policy) policyInstance;
}
Even when a Jakarta Authorization implementation has used the system property defined in this section to replace a
Policy
object used by the Jakarta Authorization implementation, the Jakarta Authorization implementation MUST be
prepared for an individual web application to replace the Policy
object once again.
For example:
@WebListener
public class PolicyRegistrationListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
PolicyFactory policyFactory = PolicyFactory.getPolicyFactory();
policyFactory.setPolicy(new TestPolicy(policyFactory.getPolicy()));
}
}
The Jakarta Authorization implementation MAY forbid setting the Policy
by an application after that application
has been taken into service (starting to process requests).
The requirements of this section have been designed to ensure that Jakarta Authorization implementations support
Policy
replacement and to facilitate delegation to a default Policy
provider. These requirements should not be
interpreted as placing any restrictions on the delegation patterns that may be implemented by replacement Policy
modules.