17 Developing Authorization

This chapter explains how to develop and configure authorization in JavaEE and JavaSE applications. It contains the following sections:

The information in this chapter assumes that you are familiar with the content in Section 13.3.3, "Programmatic Authorization."

17.1 Authorization Overview

This section compares and contrasts the authorization available in the JavaEE and the JAAS models, in the following sections:

17.1.1 Introduction to Developing Authorization

A Java 2 policy specifies the permissions granted to signed code loaded from a given location. A JAAS policy extends Java 2 grants by allowing an optional list of principals; permissions are granted only to code from a given location, possibly signed, and run by a user represented by those principals.

The Policy Store is a repository of system and application-specific policies and roles. Application roles can be granted (mapped) to enterprise users and groups specific to the application (such as administrative roles). A policy can grant permissions to any of these roles, groups, or users as principals.

For more details about policy-related security artifacts, see Chapter 3, "Policy Store Basics."

An application can delegate the enforcement of authorization to the container, or it can implement its own enforcement of policy checking with calls to methods such as checkPermission, checkBulkAuthorization, or getGrantedResources.

For details about policy checking with API calls, see Checking Policies.

17.1.2 The JavaEE Authorization Model

The JavaEE authorization model uses role membership to control access to EJB methods and web resources that are referenced by URLs; policies assign permissions to users and roles, and they are enforced by the container to protect resources.

In the JavaEE model, authorization is implemented in either of the following ways:

  • Declaratively, where authorization policies are specified in deployment descriptors; the container reads those policies from deployment descriptors and enforces them. No special application code is required to enforce authorization.

  • Programmatically, where authorization policies are checked in application code; the code checks whether a subject has the appropriate permission to execute specific sections of code. If the subject fails to have the proper permission, the code throws an exception.

Table 17-1 shows the advantages and disadvantages of each approach.

Table 17-1 Comparing Authorization in the Java EE Model

Authorization Type Advantages Disadvantages

Declarative

No coding needed; easy to update by modifying just deployment descriptors.

Authorization is coarse-grained and specified at the URL level or at the method level (for EJBs).

Programmatic

Specified in application code; can protect code at a finer levels of granularity.

Not so easy to update, since it involves code changes and recompilation.


A container can provide authorization to applications running in it in two ways: declaratively and programmatically; these topics and an example are explained in the following sections:

17.1.2.1 Declarative Authorization

Declarative authorization allows to control access to URL-based resources (such as servlets and pages) and methods in EJBs.

The basic steps to configure declarative authorization are the following:

  1. In standard deployment descriptors, specify the resource to protect, such as a web URL or an EJB method, and a logical role that has access to the resource.

    Alternatively, since JavaEE 1.5 supports annotations, use code annotations instead of deployment descriptors.

  2. In proprietary deployment descriptors (such as web.xml), map the logical role defined in step 1 to an enterprise group.

For details, see the chapter Using Security Services in Oracle Fusion Middleware Enterprise JavaBeans Developer's Guide for Oracle Containers for Java EE.

17.1.2.2 Programmatic Authorization

Programmatic authorization provides a finer grained authorization than the declarative approach, and it requires that the application code invoke the method isUserInRole (for servlets and JSPs) or the method isCallerInRole (for EJBs), both available from standard Java APIs.

Although these methods still depend on role membership to determine authorization, they give finer control over authorization decisions since the controlling access is not limited at the resource level (EJB method or URL).

17.1.2.3 JavaEE Code Example

The following example illustrates a servlet calling the method isUserInRole. It is assumed that the EAR file packing the servlet includes the configuration files web.xml and weblogic-application.xml, and that these files include the following configuration fragments:

web.xml

 <!-- security roles -->
 <security-role>
   <role-name>sr_developer</role-name>
 </security-role>

weblogic-application.xml

The following snippet shows the mapping between the user weblogic and the security role sr_developer:

<wls:security-role-assignment>
  <wls:role-name>sr_developer</wls:role-name>
  <wls:principal-name>weblogic</wls:principal-name>
</wls:security-role-assignment>

Code Example Invoking isUserInRole

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;

public class PolicyServlet extends HttpServlet {
 
 public PolicyServlet() {
        super();
    }

 public void init(ServletConfig config)
            throws ServletException {
        super.init(config);
    }

 public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        final ServletOutputStream out = response.getOutputStream();
 
        response.setContentType("text/html");
        out.println("<HTML><BODY bgcolor=\"#FFFFFF\">");
        out.println("Time stamp: " + new Date().toString());
        out.println( "<br>request.getRemoteUser = " + request.getRemoteUser() + "<br>");
        out.println("request.isUserInRole('sr_developer') = " + request.isUserInRole("sr_developer") + "<br>");
        out.println("request.getUserPrincipal = " + request.getUserPrincipal() + "<br>");
        out.println("</BODY>");
        out.println("</HTML>");
    }
}

17.1.3 The JAAS Authorization Model

The JAAS authorization introduces permissions but can still use the notion of roles. An authorization policy binds permissions with a Subject (role, group, or user) and, optionally, with source code. Granting to a role is achieved through calls to addPrincipalsToAppRole.

Permissions are evaluated by calls to the SecurityManager or the AccessController, and it allows fine-grained control to resources.

In this model, an authorization policy specifies the following information:

  • Application roles and enterprise groups.

  • Permissions granted to users, groups, and code sources. For users and groups, they determine what a user or the member of a group is allowed to access. For code sources, they determine what actions the code is allowed to perform.

When programming with this model, sensitive lines of code are preceded with calls to check whether the current user or role is granted the appropriate permissions to access the code. If the user has the appropriate permissions, the code is run. Otherwise, the code throws and exception.

For details about JAAS standard permissions, see http://java.sun.com/javase/6/docs/technotes/guides/security/permissions.html.

For details about a permission class available out-of-the-box, see Resource Permissions.

17.2 The JAAS/OPSS Authorization Model

JAAS/OPSS authorization is based on controlling the operations that a class can perform when it is loaded and run in the environment.

This section is divided into the following sections:

17.2.1 The Resource Catalog

OPSS supports the specification and runtime support of the resource catalog in both XML-based and LDAP-based policy stores. Some restrictions apply, however, to file-based policy stores; for details, see Unsupported Methods in PS2 for File-Based Policy Stores.

For a description of the application policy model using the resource catalog, see Oracle Authorization Policy Manager Administrator's Guide.

This section explains the benefits of the resource catalog model, shows configuration examples of the various resource catalog elements in XML format, describes their relevant features, and illustrates how to access them programmatically in the following sections:

For detailed description of the schema elements, see Appendix B, "File-Based Identity and Policy Store Reference."

17.2.1.1 Benefits of Using the Resource Catalog

The resource catalog improves the 11gR1 policy model by providing the following benefits:

  • Describes policies and secured artifacts in human-readable terms.

  • Allows defining and modifying policies independently of and without knowledge of the application source code.

  • Allows browsing and searching secured artifacts.

  • Allows grouping of secured artifacts in building blocks (entitlements or permission sets) which can be later used in authorization policies.

17.2.1.2 Logical Model and Configuration Examples

The resource catalog comprises resource types, resources, actions, and entitlements. The relationship between these artifacts is illustrated in Figure 17-1.

Figure 17-1 The Resource Catalog Logical Model

Surrounding text describes Figure 17-1 .

The resource catalog is specified by the following schema elements (in application jazn-data.xml or system-jazn-data.xml):

17.2.1.2.1 Resource Type

The following fragment illustrates the configuration of a resource type:

<resource-types>
  <resource-type>
    <name>TaskFlowResourceType</name>
    <display-name>TaskFlowResourceType_disp</display-name>
    <description>Resource Type for Task Flow</description>
    <provider-name>resTypeProv</provider-name>
    <matcher-class>
oracle.adf.controller.security.TaskFlowPermission</matcher-class>
    <actions-delimiter>,</actions-delimiter>
    <actions>customize,view</actions>
  </resource-type>
</resource-types>

The following points apply to the specification of a resource type:

  • The name is required and case insensitive.

  • The provider name is optional and case insensitive. A provider is typically used when there are resources managed in an external store, that is, in a store other than the OPSS domain policy store.

    When specified, the class in a <provider-name> element is used as a resource finder; queries for resources of this type (via the ResourceManager search APIs) delegate to this matcher class instead of using the built-in resource finder against the OPSS domain policy store.

  • The matcher class name is required and case sensitive.

  • The description string is optional and case insensitive.

  • The display name is optional and case insensitive.

  • The action string is optional and case sensitive. The list of actions in a resource type can be empty. An empty action list indicates that the actions on instances of the resource type are determined externally and are opaque to OPSS.

Resource type entries can be managed with WSLT commands. For details, see Section 7.4.2.11, "createResourceType," Section 7.4.2.12, "getResourceType," and Section 7.4.2.13, "deleteResourceType."

17.2.1.2.2 Resource Permissions

A permission class provides the means to control the actions that a grantee is allowed on a resource. Even though a custom permission class provides the application designer complete control over the actions, target matching, and the "implies" logic, to work as expected at runtime, a custom permission class must be specified in the system classpath of the server so that it is available and can be loaded when required. But modifying the system class path in environments is difficult and, in some environments, such modification might not be even possible.

OPSS includes the class oracle.security.jps.ResourcePermission that can be used as the permission class within any grant to protect application or system resources. Therefore, the application developer no longer needs to write custom permission classes, since the class ResourcePermission is available out-of-the-box and can be readily used in permissions within grants stored in any supported policy provider.

Configuring Resource Permissions

A permission that uses the class ResourcePermission is called a resource permission, and it specifies the resource type, the resource name, and an optional list of actions according to the format illustrated in the following XML sample:

<permission>
  <class>oracle.security.jps.ResourcePermission</class>
  <name>resourceType=type,resourceName=name</name>
  <actions>character-separated-list-of-actions</actions>
</permission>

The above specification requires that the resource type encoded in the type name be defined. Even though the resource type information is not used at runtime, its definition must be present for a resource permission to be migrated successfully; moreover, resource types help administrators model resources and manage their use. For details about resource type specifications, see Resource Type.

The following fragments illustrate the specifications of resource permissions and the corresponding required resource types:

<permission>
  <class>oracle.security.jps.ResourcePermission</class>
  <name>resourceType=epm.calcmgr.permission,resourceName=EPM_Calc_Manager</name>
</permission>

<resource-types>
  <resource-type>
    <name>epm.calcmgr.permission</name>
    <display-name>CalcManager ResourceType</display-name>
    <description>Resourcetype for managing CalcManager grants</description>
    <provider-name></provider-name>
    <matcher-class>oracle.security.jps.ResourcePermission</matcher-class>
    <actions-delimiter>,</actions-delimiter>
    <actions></actions>
  </resource-type>
</resource-types>

<permission>
  <class>oracle.security.jps.ResourcePermission</class>
  <name>resourceType=oracle.bi.publisher.Reports,resourceName=GLReports</name>
  <actions>develop;schedule</actions>
</permission>

<resource-types>
  <resource-type>
    <name>oracle.bi.publisher.Reports</name>
    <display-name>BI Publisher Reports</display-name>
    <provider-name></provider-name>
    <matcher-class>oracle.security.jps.ResourcePermission</matcher-class>
    <actions-delimiter>;</actions-delimiter>
    <actions>view;develop;schedule</actions>
  </resource-type>
</resource-types>

Note that a resource type associated with a resource permission can have an empty list of actions. The following important points apply to a resource permission:

  • The name must conform to the following format:

    resourceType=aType,resourceName=aName
    

    The resource type of a resource permission must be defined and it is returned by the method ResourcePermission.getType().

  • The character-separated list of actions is optional; if specified, it must be a subset of the actions specified in the associated resource type. This list is returned by the method ResourcePermission.getActions().

    The character used to separate the items of the list must equal to the character specified in the <actions-delimiter> of the associated resource type.

  • The display name of a resource used in a permission is returned by the method ResourcePermission.getResourceName().

  • No wildcard use is supported in a resource permission.

Resource permissions can be managed with the policy management APIs. Resource types can be managed with WLST commands. For details, see Section 7.4.2, "Managing Policies with WLST Commands."

Managing and Checking Resource Permissions

The code snippet below illustrates the instantiation of a resource permission and how to check it programmatically; the following code snippet is based on one of the configuration examples described in Configuring Resource Permissions:

ResourcePermission rp = 
   new ResourcePermission("oracle.bi.publisher.Reports","GLReports","develop");
JpsAuth.checkPermission(rp);
 

At runtime the permission check will succeed if the resource permission satisfies all the following four conditions:

  • The permission is an instance of the class ResourcePermision.

  • The resource type name (first argument) matches (ignoring case) the name of a resource type.

  • The resource (second argument) name matches exactly the name of a resource instance.

  • The list of actions (third argument) is a comma-separated subset of the set of actions specified in the resource type.

17.2.1.2.3 Resource (or Resource Instance)

A resource is associated with a resource type, and the specification of this associated resource type is required.

The following fragment illustrates the configuration of a resource (instance):

<resources>
  <resource>
    <name>resource1</name>
    <display-name>Resource1DisplayName</display-name>
    <description>Resource1 Description</description>
    <type-name-ref>TaskFlowResourceType</type-name-ref>
  </resource>
</resources>

The preceding example requires that there be a definition of the resource type referred to by the element <type-name-ref>; for the definition of the resource type TaskFlowResource, see configuration fragment in Resource Type.

Note the following points about case sensitivity of various strings in a resource entry:

  • The name is case sensitive.

  • The description string is case insensitive.

  • The display name is case insensitive.

17.2.1.2.4 Permission Set (or Entitlement)

The following fragment illustrates the configuration of a permission set (or entitlement):

<permission-sets>
  <permission-set>
    <name>permsetName</name>
    <member-resources>
      <member-resource>
         <type-name-ref>TaskFlowResourceType</type-name-ref>         <resource-name>resource1</resource-name>
         <actions>customize,view</actions>
      </member-resource>
    </member-resources>
  </permission-set>
</permission-sets>

Note the following points about a permission set:

  • The actions specified in a <member-resource> must match one or more of the actions specified for the resource type that is referenced through <resource-name-ref>.

  • A <member-resources> can have multiple <member-resource> elements in it.

  • A permission set must have at least one resource.

  • Permission sets can be exist without necessarily being referenced in any grants, that is, without granting them to any principal.

In addition, the following strings in a permission set entry conform to the case sensitivity rules:

  • The name is case insensitive.

  • The description string is case insensitive.

  • The display name is case insensitive.

17.2.1.2.5 Grant Example

The following fragment illustrates the configuration of an application policy using the resource catalog (references are not included in fragment):

      <jazn-policy>
        <grant>
          <grantee>
            <principals>
              <principal>
                <class>
              oracle.security.jps.service.policystore.ApplicationRole</class>
                <name>AppRole</name>
                <guid>F5494E409CFB11DEBFEBC11296284F58</guid>
              </principal>
            </principals>
          </grantee>
                        
          <!-- entitlement-based permissions -->
          <permission-set-refs>
            <permission-set-ref>
              <name>MyEntitlement</name>
            </permission-set-ref>
          </permission-set-refs>
        </grant>
      </jazn-policy>
    </application>      
  </applications>
 </policy-store>
 <jazn-policy></jazn-policy>
</jazn-data>

17.2.2 Managing Policies

Resource catalog artifacts can be managed with the policy management API. Specifically, the following interfaces, all subinterfaces of the interface oracle.security.jps.service.policystore.EntityManager, are directly relevant to the artifacts in the resource catalog:

  • GrantManager - This interface includes methods to query grants using search criteria, to obtain list of grants that satisfy various combinations of resource catalog artifacts, and to grant or revoke permissions to principals.

  • PermissionSetManager - This interface includes methods to create, modify, and query permission sets (entitlements).

  • ResourceManager - This interface includes methods to create, delete, and modify resource (instances).

  • ResourceTypeManager - This interface includes methods to create, delete, modify, and query resource types.

For details about these interfaces, see the Javadoc document Oracle Fusion Middleware Java API Reference for Oracle Platform Security Services.

The following code snippet illustrates the creation of a resource type, a resource instance, actions, and a permission set:

import oracle.security.jps.service.policystore.entitymanager.*;
import oracle.security.jps.service.policystore.search.*;
import oracle.security.jps.service.policystore.info.resource.*;
import oracle.security.jps.service.policystore.info.*;
import oracle.security.jps.service.policystore.*;
import java.util.*;
 
public class example {
  public static void main(String[] args) throws Exception {
     ApplicationPolicy ap;

     ResourceTypeManager rtm = ap.getEntityManager(ResourceTypeManager.class);
     ResourceTypeSearchQuery query = new ResourceTypeSearchQuery();
     query.setANDMatch();
     query.addQuery(ResourceTypeSearchQuery.SEARCH_PROPERTY.NAME, false,      ComparatorType.EQUALITY, "resourceType", BaseSearchQuery.MATCHER.EXACT);
     List<ResourceTypeEntry> allResourceTypes = rtm.getResourceTypes(query);

     ResourceManager rm = ap.getEntityManager(ResourceManager.class);
     ResourceSearchQuery ResourceQuery = new ResourceSearchQuery();
     ResourceQuery.setANDMatch();
     ResourceQuery.addQuery(ResourceSearchQuery.SEARCH_PROPERTY.NAME, false,      ComparatorType.EQUALITY, "R2", BaseSearchQuery.MATCHER.EXACT);
     List<ResourceEntry> allResources = rm.getResources("RT2", ResourceQuery);

     PermissionSetManager psm = ap.getEntityManager(PermissionSetManager.class);
     PermissionSetSearchQuery pssq = new PermissionSetSearchQuery();
     pssq.setANDMatch();
     pssq.addQuery(PermissionSetSearchQuery.SEARCH_PROPERTY.NAME, false,      ComparatorType.EQUALITY, "PS1", BaseSearchQuery.MATCHER.EXACT);
     List<PermissionSetEntry> allPermSets = psm.getPermissionSets(pssq);

     RoleCategoryManager rcm = ap.getEntityManager(RoleCategoryManager.class);
     RoleCategorySearchQuery rcsq = new RoleCategorySearchQuery();
     rcsq.setANDMatch();
     rcsq.addQuery(RoleCategorySearchQuery.SEARCH_PROPERTY.NAME, false,      ComparatorType.EQUALITY, "roleCategoryCartoon",      BaseSearchQuery.MATCHER.EXACT);

     List<RoleCategoryEntry> allRoleCategories = rcm.getRoleCategories(rcsq);
  }
}

The following code snippet illustrates a complex query involving resource catalog elements:

//ApplicationPolicy ap as in the preceeding example
ResourceTypeManager rtm = ap.getEntityManager(ResourceTypeManager.class);
ResourceTypeSearchQuery query = new ResourceTypeSearchQuery();
query.setANDMatch();
query.addQuery(ResourceTypeSearchQuery.SEARCH_PROPERTY.NAME, false, ComparatorType.EQUALITY, "resourceType", BaseSearchQuery.MATCHER.EXACT);
List<ResourceTypeEntry> enties = rtm.getResourceTypes(query);
 
ResourceManager rm = ap.getEntityManager(ResourceManager.class);
ResourceSearchQuery ResourceQuery = new ResourceSearchQuery();
ResourceQuery.setANDMatch();
ResourceQuery.addQuery(ResourceSearchQuery.SEARCH_PROPERTY.NAME, false, ComparatorType.EQUALITY, "R2", BaseSearchQuery.MATCHER.EXACT);
ArrayList<BaseSearchQuery> querries = ResourceQuery.getQueries();
List<ResourceEntry> resources = rm.getResources("RT2", ResourceQuery);
 
PermissionSetManager psm = ap.getEntityManager(PermissionSetManager.class);
PermissionSetSearchQuery pssq = new PermissionSetSearchQuery();
pssq.setANDMatch();
pssq.addQuery(PermissionSetSearchQuery.SEARCH_PROPERTY.NAME, false, ComparatorType.EQUALITY, "PS1", BaseSearchQuery.MATCHER.EXACT);
List<PermissionSetEntry> psets = psm.getPermissionSets(pssq);
 
RoleCategoryManager rcm = ap.getEntityManager(RoleCategoryManager.class);
RoleCategorySearchQuery rcsq = new RoleCategorySearchQuery();
rcsq.setANDMatch();
rcsq.addQuery(RoleCategorySearchQuery.SEARCH_PROPERTY.NAME, false, ComparatorType.EQUALITY, "roleCategoryCartoon", BaseSearchQuery.MATCHER.EXACT);
ArrayList<BaseSearchQuery> queries = rcsq.getQueries();
List<RoleCategoryEntry> rcs = rcm.getRoleCategories(rcsq);

The following code sample illustrates how to create a grant:

GrantManager gm = ap.getEntityManager(GrantManager.class);
Set<PrincipalEntry> pe = new HashSet<PrincipalEntry>();
List<AppRoleEntry> are = ap.searchAppRoles(appRoleName);
pe.addAll(are);
gm.grant(pe, null, permissionSetName);

17.2.3 Checking Policies

This section illustrates several ways to check policies programmatically, in the following sections:

Important:

Authorization failures are not visible, by default, in the console. To have authorization failures sent to the console you must set the system variable jps.auth.debug as follows: -Djps.auth.debug=true

In particular, to have JpsAuth.checkPermission failures sent to the console, you must set the variable as above.

17.2.3.1 Using the Method checkPermission

Oracle Fusion Middleware supports the use of the method checkPermission in the following standard classes:

  • java.lang.SecurityManager

  • java.security.AccessController

In addition, Oracle Fusion Middleware also supports the use of the method checkPermission in the class oracle.security.jps.util.JpsAuth.:

Oracle recommends the use of checkPermission in the class JpsAuth (instead of the previous two) because it provides better debugging support, better performance, and audit support.

The static method AccessController.checkPermission uses the default access control context (the context inherited when the thread was created). To check permissions on some other context, call the instance method checkPermission on a particular AccessControlContext instance.

The method checkPermission behaves according to the value of the JAAS mode (see JAAS mode in Chapter 14, "Configuring the Servlet Filter and the EJB Interceptor"), as listed in the following table:

Table 17-2 Behavior of checkPermission According to JAAS Mode

JAAS Mode Setting checkPermission

off or undefined

Enforces code-based security based on the security policy in effect, and there is no provision for subject-based security.

doAs

Enforces a combination of code-based and subject-based security using the access control context created through the doAs block.

doAsPrivileged

Enforces subject-based security using a null access control context.

subjectOnly

Takes into consideration grants involving principals only (and it disregards those involving codebase) when evaluating a permission.


Note:

If checkPermission is called inside a doAs block and the check permission call fails, to display the failed protection domain you must set the system property java.security.debug=access,failure.

The following example illustrates a servlet checking a permission. It is assumed that the EAR file packing the servlet includes the configuration files jazn-data.xml and web.xml.

jazn-data.xml

The application file-based policy store is as follows:

<?xml version="1.0" ?>
<jazn-data>
  <policy-store>
    <applications>
      <application>
        <name>MyApp</name>
                
        <app-roles>
        <app-role>
          <name>AppRole</name>
          <display-name>AppRole display name</display-name>
          <description>AppRole description</description>
          <guid>F5494E409CFB11DEBFEBC11296284F58</guid>
          <class>oracle.security.jps.service.policystore.ApplicationRole</class>
        </app-role>
      </app-roles>
                
      <role-categories>
        <role-category>
          <name>MyAppRoleCategory</name>
          <display-name>MyAppRoleCategory display name</display-name>
          <description>MyAppRoleCategory description</description>
        </role-category>
      </role-categories>
                
      <resource-types>
        <resource-type>
          <name>MyResourceType</name>
          <display-name>MyResourceType display name</display-name>
          <description>MyResourceType description</description>
          <provider-name>MyResourceType provider</provider-name>
          <matcher-class>oracle.security.jps.ResourcePermission</matcher-class>
          <actions-delimiter>,</actions-delimiter>
          <actions>write,read</actions>
        </resource-type>
      </resource-types>
                
      <resources>
        <resource>
          <name>MyResource</name>
          <display-name>MyResource display name</display-name>
          <description>MyResource description</description>
          <type-name-ref>MyResourceType</type-name-ref>
        </resource>
      </resources>
                
      <permission-sets>
        <permission-set>
          <name>MyEntitlement</name>
          <display-name>MyEntitlement display name</display-name>
          <description>MyEntitlement description</description>
          <member-resources>
            <member-resource>
              <type-name-ref>MyResourceType</type-name-ref>
              <resource-name>MyResource</resource-name>
              <actions>write</actions>
            </member-resource>
          </member-resources>
        </permission-set>
      </permission-sets>
                
      <jazn-policy>
        <grant>
          <grantee>
            <principals>
              <principal>
                <class>
              oracle.security.jps.service.policystore.ApplicationRole</class>
                <name>AppRole</name>
                <guid>F5494E409CFB11DEBFEBC11296284F58</guid>
              </principal>
            </principals>
          </grantee>
                        
          <!-- entitlement-based permissions -->
          <permission-set-refs>
            <permission-set-ref>
              <name>MyEntitlement</name>
            </permission-set-ref>
          </permission-set-refs>
        </grant>
      </jazn-policy>
    </application>      
  </applications>
 </policy-store>
 <jazn-policy></jazn-policy>
</jazn-data>

web.xml

The filter JpsFilter is configured as follows:

<web-app>
 <display-name>PolicyTest: PolicyServlet</display-name>
 <filter>
  <filter-name>JpsFilter</filter-name>
  <filter-class>oracle.security.jps.ee.http.JpsFilter</filter-class>
   <init-param>
    <param-name>application.name</param-name>
    <param-value>PolicyServlet</param-value>
   </init-param>
  </filter>
  <filter-mapping>
   <filter-name>JpsFilter</filter-name>
   <servlet-name>PolicyServlet</servlet-name>
   <dispatcher>REQUEST</dispatcher>
  </filter-mapping>...

Code Example

In the following example, Subject.doAsPrivileged may be replaced by JpsSubject.doAsPrivileged:

import javax.security.auth.Subject;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.security.*;
import java.util.Date;
import java.util.PropertyPermission;
import java.io.FilePermission;

public class PolicyServlet extends HttpServlet {
 
 public PolicyServlet() {
        super();
    }

 public void init(ServletConfig config)
            throws ServletException {
        super.init(config);
    }

 public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        final ServletOutputStream out = response.getOutputStream();
 
        response.setContentType("text/html");
        out.println("<HTML><BODY bgcolor=\"#FFFFFF\">");
        out.println("Time stamp: " + new Date().toString());
        out.println( "<br>request.getRemoteUser = " + request.getRemoteUser() + "<br>");
        out.println("request.isUserInRole('sr_developer') = " + request.isUserInRole("sr_developer") + "<br>");
        out.println("request.getUserPrincipal = " + request.getUserPrincipal() + "<br>");

 Subject s = null;
        s = Subject.getSubject(AccessController.getContext());
 
        out.println("Subject in servlet " + s);
        out.println("<br>");
        final RuntimePermission rtPerm = new RuntimePermission("getClassLoader");
 try {
 Subject.doAsPrivileged(s, new PrivilegedAction() {
                public Object run() {
                    try {
                        AccessController.checkPermission(rtPerm);
                        out.println("<br>");
                        out.println("CheckPermission passed for permission: " + rtPerm+ " seeded in application policy");
                        out.println("<br>");
                    } catch (IOException e) {
                        e.printStackTrace();
                        printException ("IOException", e, out);
                    } catch (AccessControlException ace) {
                        ace.printStackTrace();
                        printException ("Accesscontrol Exception", ace, out);
                    }
                    return null;
                }
            }, null);

} catch (Throwable e) {
            e.printStackTrace();
            printException("application policy check failed", e, out);
        }
        out.println("</BODY>");
        out.println("</HTML>");
    }

 void printException(String msg, Throwable e, ServletOutputStream out) {
        Throwable t;
        try {
            StringWriter sw = new StringWriter();
            PrintWriter pw = new PrintWriter(sw, true);
            e.printStackTrace(pw);
 
            out.println("<p>" + msg + "<p>");
            out.println("<code>");
            out.println(sw.getBuffer().toString());
            t = e;
            /* Print the root cause */
            while ((t = t.getCause()) != null) {
                sw = new StringWriter();
                pw = new PrintWriter(sw, true);
                t.printStackTrace(pw);
 
                out.println("<hr>");
                out.println("<p>  Caused By ... </p>");
                out.println(sw.getBuffer().toString());
            }
            out.println("</code><p>");
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }
}

17.2.3.2 Using the Methods doAs and doAsPrivileged

Oracle Fusion Middleware supports the methods doAs and doAsPrivileged in the standard class javax.security.auth.Subject.

Oracle recommends, however, the use of these methods in the class oracle.security.jps.util.JpsSubject because they render better performance and provide auditing.

Note:

If checkPermission is called inside a doAs block and the check permission call fails, to display the failed protection domain you must set the system property java.security.debug=access,failure.

17.2.3.3 Using the Method checkBulkAuthorization

The method checkBulkAuthorization determines whether a Subject has access to one or more resource actions. Specifically, the method returns the set of resource actions the passed Subject is authorized to access in the passed resources.

When invoking this method (in a JavaSE application), make sure that:

  1. The system property java.security.policy has been set to the location of the OPSS/Oracle WebLogic Server policy file.

  2. Your application calls first the method setPolicy:

    java.security.Policy.setPolicy(new oracle.security.jps.internal.policystore.JavaProvider())
    
  3. Your application calls checkBulkAuthorization() after the call to setPolicy.

In any application, checkBulkAuthorization assumes that the caller can provide:

  • A Subject with User and Enterprise Role Principals.

  • A list of resources including the stripe each resource belongs to.

Grants using resource permissions must include the required resource type. For details, see Resource Permissions.

checkBulkAuthorization also assumes that the application has visibility into the policy store stripes configured in the domain where the application is running.

checkBulkAuthorization does not require resources to be present in the policy store.

17.2.3.4 Using the Method getGrantedResources

The method getGrantedResources provides a runtime authorization query to fetch all granted resources on a given Subject by returning the resource actions that have been granted to the Subject; only permissions associated with resource types (directly or indirectly through permission sets) are returned by this method, and it is available only when the policy store is LDAP-based.

17.3 Unsupported Methods in PS2 for File-Based Policy Stores

The methods involving the following features are not supported in release 11gR1 PS2 for file-based XML policy stores (they are, however, supported when the policy store is LDAP-based):

  • Bulk authorization

  • Complex queries

  • Cascading deletions

Bulk authorization is encapsulated in the following method of the interface oracle.security.jps.service.policystore:

java.util.Set<ResourceActionsEntry>
checkBulkAuthorization(javax.security.auth.Subject subject,
                       java.util.Set<ResourceActionsEntry> requestedResources)
                       throws PolicyStoreException

Complex queries relates to any method that takes a query. When the policy store is file-based, the query must be simple; if such a method is passed a complex query and the policy store is file-based, the method will throw an exception.

A simple query is a query with just one search criterion; a complex query is a query with two or more search criteria; each call to addQuery adds a criterion to the query.

The following code fragment that illustrates the building of a simple query that returns of all permissions with a display name matching the string MyDisplayName:

PermissionSetSearchQuery query = new PermissionSetSearchQuery();
query.addQuery(PermissionSetSearchQuery.SEARCH_PROPERTY.DISPLAY_NAME,
               false,
               ComparatorType.EQUALITY,
               "MyDisplayName",
               BaseSearchQuery.MATCHER.EXACT);
getPermissionSets(query);

The following example illustrates the building of a complex query that returns all permission sets with a given resource type and a given resource instance name:

PermissionSetSearchQuery query = new PermissionSetSearchQuery();
query.addQuery(PermissionSetSearchQuery.SEARCH_PROPERTY.RESOURCE_TYPE,
               false,
               ComparatorType.EQUALITY, 
               "MyResourceType",
               BaseSearchQuery.MATCHER.EXACT);
  
query.addQuery(PermissionSetSearchQuery.SEARCH_PROPERTY.RESOURCE_NAME,
               false, 
               ComparatorType.EQUALITY, 
               "MyResourceInstanceName", 
               BaseSearchQuery.MATCHER.EXACT);
 
query.setANDMatch();
getPermissionSets(query);

Cascading deletions relates to any method that includes the Boolean argument cascadeDelete. The only value allowed for this argument in case the policy store is file-based is FALSE. Here is an example of such a method in the interface ResourceTypeManager:

void deleteResourceType(EntryReference rtRef, boolean cascadeDelete)
                 throws PolicyObjectNotFoundException,
                        PolicyStoreOperationNotAllowedException,
                        PolicyStoreException

17.4 Configuring Policy and Credential Stores for JavaSE Applications

This section explains how to configure the policy and credential stores for JavaSE applications, in the following sections:

For details about the configuration of authentication for these applications, see Section 15.2, "Developing Authentication for JavaSE Applications."

System properties should be set, as appropriate, for authorization to work in JavaSE applications. For a complete list of properties, see Section F.1, "OPSS System Properties."

17.4.1 Configuring LDAP-Based Policy and Credential Stores

This section assumes that an LDAP-based store has been set to be used as the policy and credential stores; for details about setting up nodes in an Oracle Internet Directory, see section Section 7.1.2, "Prerequisites to Using an LDAP-Based Policy Store."

A JavaSE application can use LDAP-based policy and credential stores, and the specifics of these services are configured in the application file jps-config-jse.xml.

The following fragments illustrate the configurations of instances of LDAP-based policy and credential stores:

<serviceInstance provider="ldap.policystore.provider" name="policystore.ldap">
  <property value="OID" name="policystore.type"/>
  <property value="bootstrap" name="bootstrap.security.principal.key"/>
  <property value="cn=PS1domainRC3" name="oracle.security.jps.farm.name"/>
  <property value="cn=myTestNode" name="oracle.security.jps.ldap.root.name"/>
  <property value="ldap://myComp.com:1234" name="ldap.url"/>       </serviceInstance>

<serviceInstance provider="ldap.credentialstore.provider" name="credstore.ldap">
  <property value="bootstrap" name="bootstrap.security.principal.key"/>
  <property value="cn=PS1domainRC3" name="oracle.security.jps.farm.name"/>
  <property value="cn=myTestNode" name="oracle.security.jps.ldap.root.name"/>
  <property value="ldap://myComp.com:1234" name="ldap.url"/>
</serviceInstance>

The following fragment illustrates the configuration of the bootstrap credentials file (cwallet.sso), which allows the program access to the LDAP server:

<serviceInstance location="./bootstrap" provider="credstoressp" name="bootstrap.cred">
  <property value="./bootstrap" name="location"/>
</serviceInstance>

The following fragment illustrates the configuration of the necessary jpsContexts that reference the instances above:

<jpsContexts default="TestJSE">
  <jpsContext name="TestJSE">
    <serviceInstanceRef ref="policystore.ldap"/>
    <serviceInstanceRef ref="credstore.ldap"/>
  </jpsContext>
  <jpsContext name="bootstrap_credstore_context">
    <serviceInstanceRef ref="bootstrap.cred"/>  
  </jpsContext>
</jpsContexts>

The following code fragment illustrates how to obtain programmatically a reference to the LDAP-based policy store configured above, and it assumes that the following system properties have been set in the environment:

  • jps.policystore.hybrid.mode, set to true.

  • oracle.security.jps.config, set to the location of the file jps-config-jse.xml.

String contextName="TestJSE"; ...
public static PolicyStore getPolicyStore(String contextName) {
      try-block    
            JpsContextFactory ctxFact;  
            ctxFact = JpsContextFactory.getContextFactory();   
            JpsContext ctx = ctxFact.getContext(contextName);  
            return ctx.getServiceInstance(PolicyStore.class);      
      catch-block
...

17.4.2 Configuring File-Based Policy and Credential Stores

A JavaSE application can use file-based policy and credential stores, and the specifics of these services are configured in the application file jps-config-jse.xml.

A file-based policy store is specified in the file system-jazn-data.xml; a file-based credential store is specified in the file cwallet.sso (this wallet file should not be confused with the bootstrap file, also named cwallet.sso, which contains the credentials to access LDAP stores, when the application security is LDAP-based).

For details about wallets, see Section 14.4.3, "Using a Wallet-Based Credential Store," and Section 8.5.2.5, "modifyBootStrapCredential."

The following fragments illustrate the configuration of file-based policy and credential stores, and the jpsContext that reference them:

<serviceProviders>
  <serviceProvider type="CREDENTIAL_STORE" name="credstoressp"
        class="oracle.security.jps.internal.credstore.ssp.SspCredentialStoreProvider">
    <description>SecretStore-based CSF Provider</description>
  </serviceProvider>
  <serviceProvider type="POLICY_STORE" name="policystore.xml.provider"
        class="oracle.security.jps.internal.policystore.xml.XmlPolicyStoreProvider">
    <description>XML-based PolicyStore Provider</description>
  </serviceProvider>
</serviceProviders>

<serviceInstances>
  <serviceInstance name="credstore" provider="credstoressp" location="./">
    <description>File-based Credential Store Service Instance</description>
  </serviceInstance>
 
  <serviceInstance name="policystore.xml" provider="policystore.xml.provider" location="./system-jazn-data.xml">
    <description>File-based Policy Store Service Instance</description>
  </serviceInstance>
</serviceInstances>

<jpsContexts default="TestJSE">
  <jpsContext name="TestJSE">
            <serviceInstanceRef ref="credstore"/>
            <serviceInstanceRef ref="policystore.xml"/>
    ...
  </jpsContext>
  ...
</jpsContexts>