Skip Headers
Oracle® Fusion Middleware Application Security Guide
11g Release 1 (11.1.1)

Part Number E10043-12
Go to Documentation Home
Home
Go to Book List
Book List
Go to Table of Contents
Contents
Go to Index
Index
Go to Master Index
Master Index
Go to Feedback page
Contact Us

Go to previous page
Previous
Go to next page
Next
PDF · Mobi · ePub

19 Integrating Application Security with OPSS

This chapter describes a number of security-related use cases and the typical life cycle of an ADF application security. It also lists code and configuration samples presented elsewhere in this Guide.

This chapter contains the following sections:

19.1 Introduction

The audience for the material presented in this chapter are developers, security architects, and security administrators. The presentation is not feature-driven, as in most topics in this Guide, but use case-driven: a number of use cases that solve typical application security challenges are introduced as a departing point to solve particular application security requirements. Some of the use cases describe a declarative approach (and do not require changes in application code); others provide a programmatic approach; and others require both approaches.

The top security issues that security architects and developers face include managing users, user passwords, and access to resources. OPSS is a suite of security services that provides solutions to these challenges by supporting:

Figure 19-1 illustrates how applications access the security stores and the tools to manage those stores.

Figure 19-1 Applications, Security Stores, and Management Tools

Surrounding text describes Figure 19-1 .

Links to Related Documentation

Topics explained elsewhere include the following:

For the list of OPSS APIs, see Appendix H, "References."

19.2 Security Integration Use Cases

This section introduces a number of use cases categorized according to a main security feature or security artifact, in the following sections:

Each use case contains a brief description of the problem it attempts to solve, the security artifacts required, the features involved, and links to details solving the stated problem. Unless otherwise stated, all the descriptions apply to the Oracle WebLogic Application Server and to the WebSphere Application Server.

19.2.1 Authentication

The authentication use cases are the following:

19.2.1.1 Java EE Application Requiring Authenticated Users

In order to access a Java EE application, users must be authenticated against the identity store in cases where the identity store is any of the following:

  • Single LDAP-based store

  • Several LDAP-based stores of the same kind (such as all OID, for example)

  • Several LDAP-based stores of different kinds; in particular two LDAP-based stores: one AD LDAP and a second one OID LDAP

  • Single DB-based store

  • Several LDAP- and DB-based stores

This use case requires:

  • Allowing access to the application to only authenticated users

  • Not modifying the application code, even when customers have user identities in different repositories

This use case features:

  • Deploying an application to a WebLogic container

  • Configuring the appropriate authenticators according to the particular set of user repositories

  • Configuring the OVD authenticator in case of a mixed LDAP types or mixed LDAP and DB types

According to the repository used, the details of this use case are split into the following scenarios:

  • Single user repository - Configure the appropriate authenticator with the WebLogic console

  • Multiple user repositories (or split profiles across LDAP of the same of different kinds) - Configure the OVD authenticator

  • DB-based repositories - Configure the OVD authenticator

For details, see Section 3.1.2, "Oracle WebLogic Authenticators."

19.2.1.2 Java EE Application Requiring Programmatic Authentication

A Java EE application, not using deployment descriptors, must authenticate the user programmatically against the configured identity store(s); it applies only to Java EE applications deployed to the Oracle WebLogic Application Server.

This use case requires using the OPSS public API to authenticate a user, and it features:

  • Configuring authenticators for a Java EE container

  • Using the LoginService API to authenticate the user

For details about this use case, see Section 22.1, "Links to Authentication Topics for Java EE Applications."

19.2.1.3 Java SE Application Requiring Authentication

A Java SE application must authenticate users against the LDAP identity store in use in a domain; the application code requesting authentication must be same regardless of the specifics of the domain's identity store.

This use case requires configuring the identity store(s) against which the authentication should take place and using the LoginService; note that a Java SE application can use only one id login module.

For details about this use case, see Section 22.2.4, "Using the OPSS API LoginService in Java SE Applications."

19.2.2 Identities

The identity use cases are the following:

19.2.2.1 Application Running in Two Environments

An application, which runs in two different environments, needs to access user profile information, such as a user's email address, stored in an LDAP-based store; the LDAP server can be of any of the supported types and that type may differ with the environment. For details on supported types, see Section 4.1, "Supported LDAP-, DB-, and File-Based Services."

More specifically, this use case assumes that:

  • The application uses the method UserProfile.getEmail().

  • In one environment, there is an AD LDAP configured as follows:

    mail.attr = msad_email
    
  • In the second environment, there is an OID LDAP configured as follows:

    mail.attr = mail
    

In order for the application to retrieve the correct information without modifying the code and regardless of the environment (first or second) in which it runs, the identity store provider must be configured with the correct property in each of those two environments.

In the first environment (AD LDAP), the identity store provider is set to have the following property:

<property name="mail.attr" value="msad_mail">

In the second one (OID LDAP), the identity store provider is set to have the following property:

<property name="mail.attr" value="mail"

For details about this use case, see Section 7.2, "Configuring the Identity Store Provider."

19.2.2.2 Application Accessing User Profiles in Multiple Stores

An application needs access to user profile information located in more than one LDAP-based stores.

This use case requires configuring the environment for multiple LDAP-based stores.

For details about:

19.2.3 Authorization

The authorization use cases are the following:

19.2.3.1 Java EE Application Accessible by Specific Roles

A Java EE application needs to be accessible only by users that had been assigned specific roles in web descriptors; the group-to-role assignment must be configurable at deployment based on the customer's environment.

For details about this use case, see sections Using Declarative Security with Web Applications and Using Declarative Security with EJBs in Oracle Fusion Middleware Programming Security for Oracle WebLogic Server.

19.2.3.2 ADF Application Requiring Fine-Grained Authorization

An ADF application in container requires fine-grained authorization at the level of individual controls on the pages in the web application; while the application initiates the authorization check, the policies need to be externalized and customizable per customer post application deployment.

For details on how to develop and secure Oracle ADF applications, see chapter 30, Enabling ADF Security in a Fusion Web Application, in Oracle Fusion Middleware Fusion Developer's Guide for Oracle Application Development Framework.

For general information about ADF applications, see Section 1.5.2, "Scenario 2: Securing an Oracle ADF Application."

For details about the life cycle of an ADF application, see Appendix - Security Life Cycle of an ADF Application.

19.2.3.3 Web Application Securing Web Services

A web application requires securing web services with fine grained policies.

For details about web services security administration, see Oracle Fusion Middleware Security and Administrator's Guide for Web Services.

19.2.3.4 Java EE Application Requiring Codebase Permissions

A Java EE application requires codebase permissions to perform specific actions; typical examples are reading a credential from the credential store or looking up policies in the policy store.

For details about creating codebase policies with Fusion Middleware Control, see Section 9.2.3, "Managing System Policies."

19.2.3.5 Non-ADF Application Requiring Fine-Grained Authorization

A non-ADF application needs to be secured with fine-grained authorization checks.

This use case requires:

  • Placing checks in the application code at the appropriate places

  • Configuring the appropriate policies

For details see Section 20.3, "The JAAS/OPSS Authorization Model."

19.2.4 Credentials

The credential use case is the following:

19.2.4.1 Application Requiring Credentials to Access System

An application requires a credential to connect to a back-end system, such as a database or an LDAP server. The application code should reference this credential in such a way that the specifics of the credential can be changed per customer post deployment without modifying the application code. Furthermore, this use case also requires specifying who can access the credential store and what operations an authorized user can perform on credential data.

This use case features:

  • Using the credential store to persist credentials

  • Fetching credentials at runtime with the CSF API in application code

  • Defining and enforcing system policies on codebase

For details about:

19.2.5 Audit

The audit use cases are the following:

19.2.5.1 Auditing Security-Related Activity

An application needs to record security-related activity in several security areas; specifically, the application requires logging the following information:

  • Changes to a policy: what and when

  • The policies that were evaluated in a particular time interval

  • Changes to credentials or keys: what and when

The settings explained in this use case apply to all applications and components in a domain.

This use case requires that auditable applications:

  • Integrate with the Common Audit Framework (CAF)

  • Have built-in capabilities to log security activities

  • Set the proper audit filter level to capture activities in specific security areas

This use case features:

  • Integrating with the Common Audit Framework

  • Allowing applications to define their own audit categories and events in security areas, and making the application audit-aware

  • Allowing applications to set the appropriate filter level

For details about:

19.2.5.2 Auditing Business-Related Activity

An application needs to record business-related activity in the context of a functional flow; specifically, the application requires logging the users and the business actions performed by them in a particular time interval.

The settings explained in this use case apply to all applications and components in a domain.

This use case requires that applications:

  • Create their own audit events based on their business needs

  • Be able to log business activities with runtime attributes to audit data repository

  • Generate audit reports from audit events

  • Manage runtime audit policies

  • Modify audit event definitions, if necessary

This use case features:

  • Allowing applications to define business functional areas (as audit categories), business activities (as audit events in categories), and attributes in each category.

  • Registering applications at deployment; updating audit definitions; deregistering applications after deployment.

  • Managing audit artifacts with Fusion Middleware Control or WSLT scripts.

For details about:

19.2.6 Identity Propagation

The identity propagation use cases are the following:

19.2.6.1 Propagating the Executing User Identity

A client application in container needs to propagate the executing user identity to a web service over SOAP; the web service can be running on a different managed server, in the same domain, or in a different domain.

This use case requires that the current executing user identity be propagated to a web service over SOAP.

The features that facilitate this use case are primarily those of Oracle Web Services Manager (OWSM).

For details about OWSM, see chapter 4, Examining the Rearchitecture of Oracle Web Services Manager in Oracle Fusion Middleware, in Oracle Fusion Middleware Security and Administrator's Guide for Web Services.

For details about propagating identities over SOAP, see chapter 11, Configuring Policies, in Oracle Fusion Middleware Security and Administrator's Guide for Web Services.

19.2.6.2 Propagating a User Identity

A client application in container needs to propagate a user identity (which is not the executing user identity) to a web service over SOAP; the identity to be propagated is stored in the OPSS security store.

This use case requires that an identity of a user, distinct from the current executing user, be propagated to a web service over SOAP.

This use case features:

  • The OPSS security store, where credentials are stored, from where the application gets the specific identity that needs to be propagated as a PasswordCredential.

  • Oracle Web Services Manager ability to fetch and propagate the identity to a remote web service.

For details about this use case, see chapter 9, Creating and Managing Policies Sets, in Oracle Fusion Middleware Security and Administrator's Guide for Web Services.

19.2.6.3 Propagating Identities Across Domains

A client application in container in a WebLogic domain needs to propagate a user identity (stored in the OPSS security store) to a different WebLogic domain over RMI.

For details about this use case, see section Enabling Trust Between WebLogic Server Domains in shar.

19.2.6.4 Propagating Identities over HTTP

A client application in container (in a WebLogic domain or a WAS cell) needs to propagate identities over HTTP.

For requirements and details about this use case, see Propagating Identities over HTTP.

19.2.7 Administration and Management

The administration use cases are the following:

19.2.7.1 Application Requiring a Central Store

An application requires a central repository of policies, credentials, audit configuration, trusts, and keys, and a set of tools to manage that central repository, which is the OPSS security store.

This use case features:

  • The OPSS security store

  • Managing security artifacts with Fusion Middleware Control

  • Managing security artifacts with WLST scripts

For details about:

19.2.7.2 Application Requiring Custom Management Tool

An application requires a custom tool to manage externalized security artifacts in a context that is meaningful to the application's business.

This use case requires building a custom graphical user interface with calls to OPSS APIs to display and manage security artifacts in the OPSS security store in a context that is meaningful to the application.

This use case features:

  • Managing security artifacts with OPSS API

For details about:

19.2.7.3 Application Running in a Multiple Server Environment

Application running in a WebLogic domain where several server instances are distributed across multiple machines requires modifying security artifacts; changes must take effect in all components of the application regardless of where they are running.

This use case features:

  • Propagating changes to security artifacts whenever those changes are initiated on the administration server; data on managed server nodes is refreshed based on caching policies.

  • Using the MBeans API or Management API to modify security artifacts.

For details about:

19.2.8 Integration

The integration use case is the following:

19.2.8.1 Application Running in Multiple Domains

A product requires multiple WebLogic domains to run and those domains share a single central OPSS security store.

This use case features:

  • OPSS support for several domains to share a security store

For details about:

19.3 Some Use Cases Details

This section describes the following use cases in some detail:

19.3.1 Propagating Identities over HTTP

This section explains how an identity can be propagated across containers and domains using the OPSS trust service and the HTTP protocol.

19.3.1.1 The OPSS Trust Service

The OPSS trust service allows the propagation of identities across HTTP-enabled applications by providing and validating tokens. The OPSS trust service uses an asserter that is available only on the following platforms:

  • Oracle WebLogic Application Server - the Identity Asserter

  • IBM WebSphere Application Server - the Trust Asserter Interceptor (TAI)

Even though the scenarios in this section are illustrated with applications running on WebLogic domains, they also apply to applications running on WebSphere cells; except for the asserter configuration, all other configurations and samples are identical on both platforms. For configuration properties, see Section F.2.6, "Trust Service Properties."

There is one asserter per WebLogic domain or WebSphere cell; the keystore stores digital certificates, private keys, and trusted CA certificates; the storage service used by the keystore is JKS.

19.3.1.2 Propagating Identities over the HTTP Protocol

Identity propagation using HTTP calls typically runs as follows (see Figure 19-2):

  1. A client application in Domain1 requests a token for an authenticated user from Domain1's OPSS trust service instance.

  2. The trust service accesses Domain1's keystore and issues a token to the client application.

  3. The client application encodes the token in an HTML header and dispatches an HTTP request to a servlet application in Domain2. Domain 2's asserter intercepts the request and extracts the token.

  4. The asserter requests a validation of that token from Domain2's OPSS trust service instance.

  5. The trust service accesses Domain2's keystore to validate the token and returns a response.

  6. Assuming that the validation is successful, the asserter sends the request to the servlet application using the asserted identity.

  7. The servlet application sends an HTTP response to the client application request.

Figure 19-2 Identity Propagation with HTTP Calls

Surrounding text describes Figure 19-2 .

The remainder of this section explains and illustrates the configuration required for the above scenario to work, in the following sections:

19.3.1.2.1 Single Domain Scenario

In this scenario, the client and the servlet applications use the same trust service instance to issue and validate tokens. The following code and configuration samples illustrate a sample client and a servlet applications running in the same domain.

Client Application Code Sample

The following sample illustrates a client application; note that the file jps-api.jar must be included the class path for the code to compile.

// Authentication type name
public static final String AUTH_TYPE_NAME = "OIT";
// The authenticated username
String user = "weblogic"; 
// URL of the target application
URL url = "http://host:port/destinationApp"; 
//-----------------------------------------
JpsContextFactory ctxFactory = JpsContextFactory.getContextFactory();
JpsContext jpsCtx = ctxFactory.getContext();
final TrustService trustService = jpsCtx.getServiceInstance(TrustService.class);
final TokenManager tokenMgr = trustService.getTokenManager();
final TokenContext ctx = tokenMgr.createTokenContext(
    TokenConfiguration.PROTOCOL_EMBEDDED);
UsernameToken ut = WSSTokenUtils.createUsernameToken("wsuid", user);
GenericToken gtok = new GenericToken(ut);
ctx.setSecurityToken(gtok);
ctx.setTokenType(SAML2URI.ns_saml);
Map<String, Object> ctxProperties = ctx.getOtherProperties();
ctxProperties.put(TokenConstants.CONFIRMATION_METHOD,
    SAML2URI.confirmation_method_bearer);
 
AccessController.doPrivileged(new PrivilegedAction<String>() {
    public String run() {
        try {
            tokenMgr.issueToken(ctx);
        } catch (Exception e) {        
            e.printStackTrace();
        }
        return null;
    }
});
 
Token token = ctx.getSecurityToken();
String b64Tok = TokenUtil.encodeToken(token);
 
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setDoOutput(true);
connection.setReadTimeout(10000);
connection.setRequestProperty("Authorization", AUTH_TYPE_NAME + " " + b64Tok);
connection.connect();
BufferedReader rd = new BufferedReader(new InputStreamReader(
    connection.getInputStream()));
StringBuilder sb = new StringBuilder();
 
String line = null;
while ((line = rd.readLine()) != null) {
    sb.append(line);
}
connection.disconnect();
System.out.println(sb.toString());

Keystore Service Configuration

Assuming that the domain name is jrfServer_admin, the following command illustrates the creation of the domain keystore, represented by the generated file default-keystore.jks:

JAVA_HOME/bin/keytool -genkeypair 
  -alias jrfServer_admin 
  -keypass welcome 
  -keyalg RSA 
  -dname "CN=jrfServer_admin,O=Oracle,C=US" 
  -keystore default-keystore.jks 
  -storepass password
 
cp default-keystore.jks ${domain.home}/config/fmwconfig

Make sure that the keystore service configured in the file jps-config.xml points to the generated default-keystore.jks; the following sample illustrates a keystore service configuration:

<!-- KeyStore Service Instance -->
<serviceInstance name="keystore" 
    provider="keystore.provider"  location="./default-keystore.jks">
    <description>Default JPS Keystore Service</description>
    <property name="keystore.provider.type" value="file"/>
    <property name="keystore.file.path" value="./"/>
    <property name="keystore.type" value="JKS"/>
    <property name="keystore.csf.map" value="oracle.wsm.security"/>
    <property name="keystore.pass.csf.key" value="keystore-csf-key"/>
    <property name="keystore.sig.csf.key" value="sign-csf-key"/>
    <property name="keystore.enc.csf.key" value="enc-csf-key"/>
</serviceInstance >

CSF Configuration

Create a map/key pair used to open the keystore and another map/key pair used to issue tokens. The following commands illustrate these operations using the OPSS script createCred:

// JKS keystore opening password
createCred(map="oracle.wsm.security", key="keystore-csf-key", 
           user="keystore", password="password") 
 
// Private key password to issue tokens
createCred(map="oracle.wsm.security", key="sign-csf-key", 
           user="orakey", password="password")

For details about the OPSS script createCred, see Section 10.5, "Managing Credentials with OPSS Scripts."

Grant Configuration

Add a grant like the following to the policy store, which allows the client application to use the trust service API:

<grant>
  <grantee>
    <codesource>    
      <url>file:${oracle.deployed.app.dir}/<MyApp>${oracle.deployed.app.ext}</url>
    </codesource>
  </grantee>
  <permissions>
    <permission>          
<class>oracle.security.jps.service.trust.TrustServiceAccessPermission</class>
        <name>appId=*</name>
        <actions>issue</actions>
     </permission>
    </permissions>
</grant>

The Oracle WebLogic Server must be stopped and re-started for the above grant to take effect.

Servlet Code

The following sample illustrates how a servlet can obtain an asserted user name:

public void doGet(HttpServletRequest request, HttpServletResponse response)
   throws ServletException, IOException {
   String username = request.getRemoteUser();
   ServletOutputStream out = response.getOutputStream();
   out.print("Asserted username: " + username);
   out.close();
}

web.xml Configuration

Set the appropriate login method in the file web.xml, as illustrated in the following snippet:

<web-app id="WebApp_ID"
…
 <login-config>
   <auth-method>CLIENT-CERT</auth-method>
   <realm-name>Identity Assertion</realm-name>
 </login-config>
…
</web-app>

WebLogic Asserter and Trust Service Configuration

To configure the WebLogic asserter, proceed as follows:

  1. Copy the WebLogic identity asserter JAR jps-wls-trustprovider.jar to the location ${domain.home}/lib/mbeantypes, as illustrated by the following command, and then restart the WebLogic Server:

    cp ${common.components.home}/modules/oracle.jps_11.1.1/jps-wls-trustprovider.jar ${domain.home}/lib/mbeantypes
    
  2. Use WebLogic Console to configure the asserter, as follows:

    1. Login to the console as an administrator.

    2. Navigate to Security Settings > Security Realms > myrealm > Providers Tab > Authentication, and click New to open the Create a New Authentication Provider dialog.

    3. In that dialog, enter TrustServiceIdentityAsserter in the name box, and select TrustServiceIdentityAsserter from the pull-down in the type box; then click OK.

  3. Verify that a grant like the following is present in the policy store; this grant is required for the asserter to use the OPSS trust service API; if necessary, use WSLT scripts to specify the grant:

    <grant>
        <grantee>
            <codesource>
                <url>file:${domain.home}/lib/mbeantypes/jps-wls-trustprovider.jar</url>
            </codesource>
        </grantee>
        <permissions>
            <permission>
                <class>oracle.security.jps.service.trust.TrustServiceAccessPermission</class>
                <name>appId=*</name>
                <actions>validate</actions>
            </permission>
        </permissions>
    </grant>
    

    Any changes to the file jps-config.xml) requires the server to be re-started before updates take effect.

WebSphere Trust Asserter Interceptor Configuration

For details on this topic, see section Configuring the Trust Association Interceptor in Oracle Fusion Middleware Third-Party Application Server Guide.

19.3.1.2.2 Multiple Domain Scenario

In this scenario there are two different domains: Domain1 and Domain2. The client application is running in Domain1; the servlet application is running in Domain2. It is assumed that each of these two domains have each a trust store service and keystore properly configured as explained under the heading WebLogic Asserter and Trust Store Configuration in the Single Domain Scenario. In this scenario, the client application uses Domain1's trust service for token generation, and the servlet application uses Domain2's trust service for token validation.

In Domain1, the client sample code and the following configurations are identical to those described in the Single Domain Scenario:

  • the client application is illustrated by the code under the heading Client Application Code Sample.

  • the configuration of the keystore is illustrated under the heading Keystore Service Configuration.

  • the CSF configuration is illustrated under the heading CSF Configuration.

  • the grant configuration is illustrated under the heading Grant Configuration.

In Domain 2, the servlet sample code and web.xml configuration are identical to those described in the Single Domain Scenario, but there is some extra setup required:

  • The servlet application code is illustrated by the code under the heading Servlet Code in the Single Domain Scenario.

  • The configuration of the file web.xml is illustrated under the heading web.xml Configuration in the Single Domain Scenario.

  • The client certificate that is used to sign the token in Domain1 must be present in Domain2's keystore; therefore, the administrator proceeds as follows:

    1. Exports the certificate from Domain 1's keystore, as illustrated by the following command:

      JAVA_HOME/bin/keytool -export
      -alias jrfServer_admin.cer
      -keystore default-keystore.jks
      -storepass password
      
    2. Imports the certificate into Domain 2's keystore as illustrated by the command below. Note that the alias passed must be the same as the alias used in step 1 for the export; if you overwrite the issuer name in the client side then that issuer name should be used as the alias.

      JAVA_HOME/bin/keytool -importcert 
        -alias jrfServer_admin 
        -keypass welcome 
        -keyalg RSA 
        -dname "CN=jrfServer_admin,O=Oracle,C=US" 
        -keystore default-keystore.jks 
        -storepass password
      
    3. Sets the Domain2's keystore password in the (Domain2's) credential store using the OPSS script createCred as follows:

      createCred(map="oracle.wsm.security", key="keystore-csf-key", user="keystore", password="password")
      

19.3.1.3 Domains Using Both Protocols

In this scenario, applications use either the HTTP protocol or the SOAP protocol, and not all applications in the domain use the same protocol. In such scenario, the keystore can be shared by the trust service used by the HTTP protocol and the SOAP service used by Oracle Web Services Manager. But in order for the trust service to work in this case, some special configurations in the file jps-config.xml are required as explained in the following sections:

19.3.1.3.1 Single Domain Scenario

In this scenario, there is one keystore. The following snippet illustrates the configuration required for a certificate with alias orakey:

<propertySet name="trust.provider.embedded">
    <property name="trust.provider.className"
     value="oracle.security.jps.internal.trust.provider.embedded.EmbeddedProviderImpl"/>
    <property name="trust.clockSkew" value="60"/>
    <property name="trust.token.validityPeriod" value="1800"/>
    <property name="trust.token.includeCertificate" value="false"/>
    
    <!-- The alias used to get the signing certificate from JKS -->
    <property name="trust.aliasName" value="orakey"/> 
 
    <!-- The issuer name to be added in the token used by the destination
    trust service instance as an alias to pick up the corresponding certificate 
    to validate the token signature -->
    <property name="trust.issuerName" value="orakey"/>
</propertySet>
19.3.1.3.2 Multiple Domain Scenario

In this scenario, there are two domains and two keystores. The following snippet illustrates the configuration required in the domain that is issuing tokens for a certificate with alias orakey:

<!-- issuer domain trust store must have a signing certif. w. alias orakey -->
<propertySet name="trust.provider.embedded">
    <property name="trust.provider.className"
        value="oracle.security.jps.internal.trust.provider.embedded.EmbeddedProviderImpl"/>
    <property name="trust.clockSkew" value="60"/>
    <property name="trust.token.validityPeriod" value="1800"/>
    <property name="trust.token.includeCertificate" value="false"/>
 
    <!-- the signing certificate alias in local JKS -->
    <property name="trust.aliasName" value="orakey"/> 
    
    <!-- the token issuer's name -->
    <property name="trust.issuerName" value="domain1"/> 
</propertySet>

The following snippet illustrates the configuration required in the domain that is receiving tokens for a certificate with alias orakey:

<!- important: recipient domain must have a token validation certificate for domain1, 
which is the one was used to sign the token with alias "domain1" -->
<propertySet name="trust.provider.embedded">
    <property name="trust.provider.className"
        value="oracle.security.jps.internal.trust.provider.embedded.EmbeddedProviderImpl"/>
    <property name="trust.clockSkew" value="60"/>
    <property name="trust.token.validityPeriod" value="1800"/>
    <property name="trust.token.includeCertificate" value="false"/>
    
    <!-- the signing certificate alias in local JKS -->
    <property name="trust.aliasName" value="orakey"/> 
 
    <!-- the token issuer's name -->
    <property name="trust.issuerName" value="domain2"/> 
</propertySet>

19.3.2 A Custom Graphical User Interface

This use case illustrates some of the operations needed, for example, when implementing a custom graphic UI to manage policies. The samples presented use the OPSS APIs and demonstrate the following operations:

  • Querying users in the identity store.

  • Querying application roles in the policy store.

  • Querying the mapping of users and groups to application roles; specifically, given a user identify all the application roles mapped to that user (Recall that the mapping of users and groups to application roles is a many-to-many relationship).

  • Creating, reading, updating, and deleting the mapping of users and groups to application roles.

This use case assumes that:

  • The identity store is an OID LDAP-based store.

  • The policy store is an OID LDAP-based store.

  • The identity store contains the following hierarchy of users and groups (enterprise roles):

    • The users Mary, John, Tom, and Helen.

    • The groups IT, Training, and Development.

    • The groups Training and Development are members of the group IT.

    • The user Mary is a member of the group Training.

    • The users Tom and John are members of the group Development.

  • The policy store contains the following application policies and hierarchy of application roles:

    • The application policies ApplicationPolicy1 and ApplicationPolicy2.

    • The roles System Manager, System Developer, and System Analyst are application roles referenced in the policy ApplicationPolicy1; the System Manager role is a member of the System Developer role; the System Developer role is a member of the System Analyst role.

    • The roles Director, Instructor, and Lecturer are application roles referenced in the application policy ApplicationPolicy2; the Director role is a member of the Instructor role; the Instructor role is member of the Lecturer role.

  • The mapping of application roles to users and groups is as follows:

    • The role System Manager is mapped to the user Helen.

    • The role System Developer is mapped to the group Development.

    • The role Director is mapped to the user Tom.

    • The role Instructor is mapped to the groups Training and Development.

Figure 19-3 illustrates the hierarchy of application roles, the users and groups, and the mapping of application roles to users and groups, as assumed in this use case.

Figure 19-3 Mapping of Application Roles to Users and Groups

Surrounding text describes Figure 19-3 .

Note that the above role hierarchy implies, for instance, that a user in the System Manager role is also in the System Developer role, and similarly with the other roles. Therefore the role membership for each of the four users is as follows:

  • User Tom is a member of the following application roles: System Developer, System Analyst, Director, Instructor, and Lecturer.

  • User Helen is a member of the following application roles: System Manager, System Developer, and System Analyst.

  • User Mary is a member of the following application roles: Instructor and Lecturer.

  • User John is a member of the following application roles: System Developer, System Analyst, Instructor, and Lecturer.

The code samples are detailed in the following sections:

19.3.2.1 Imports Assumed

The sample codes in this use case assume the following import statements:

import java.security.AccessController;
import java.security.Policy;
import java.security.Principal;
import java.security.PrivilegedExceptionAction;
import java.security.Security;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.security.auth.Subject;
import oracle.security.idm.Identity;
import oracle.security.idm.IdentityStore;
import oracle.security.idm.ObjectNotFoundException;
import oracle.security.idm.Role;
import oracle.security.idm.RoleManager;
import oracle.security.idm.SearchParameters;
import oracle.security.idm.SearchResponse;
import oracle.security.idm.SimpleSearchFilter;
import oracle.security.idm.User;
import oracle.security.idm.UserProfile;
import oracle.security.jps.ContextFactory;
import oracle.security.jps.JpsContext;
import oracle.security.jps.JpsContextFactory;
import oracle.security.jps.principals.JpsApplicationRole;
import oracle.security.jps.service.idstore.IdentityStoreService;
import oracle.security.jps.service.policystore.ApplicationPolicy;
import oracle.security.jps.service.policystore.PolicyObjectNotFoundException;
import oracle.security.jps.service.policystore.PolicyStore;
import oracle.security.jps.service.policystore.PolicyStoreException;
import oracle.security.jps.service.policystore.entitymanager.AppRoleManager;
import oracle.security.jps.service.policystore.info.AppRoleEntry;
import oracle.security.jps.service.policystore.search.AppRoleSearchQuery;
import oracle.security.jps.service.policystore.search.ComparatorType;
import oracle.security.jps.util.JpsAuth;
import weblogic.security.principal.PrincipalFactory;

19.3.2.2 Code Sample 1

The following sample code illustrates two queries to users in the identity store:

private void queryUsers() throws Exception {
        // Using IDM U/R to query ID store
        IdentityStore idmStore = idStore.getIdmStore();
 
        // Query an individual user by name
        User employee = idmStore.searchUser(USER_TOM);
        log("----------------------------------------------------------");
        log("### Query individual user (Tom) from ID store ###");
        log(USER_TOM + ": " + employee.getName() + " GUID: " +
            employee.getGUID());
        log();
 
        // Get all users whose name is not "Paul"
        SimpleSearchFilter filter =
            idmStore.getSimpleSearchFilter(UserProfile.NAME,
                                           SimpleSearchFilter.TYPE_NOTEQUAL,
                                           "Paul");
        SearchParameters sps =
            new SearchParameters(filter, SearchParameters.SEARCH_USERS_ONLY);
        SearchResponse result = idmStore.searchUsers(sps);
        log("----------------------------------------------------------");
        log("### Query all users (whose name is not Paul) from ID store ###");
        log("Found the following users:");
        while (result.hasNext()) {
            Identity user = result.next();
            log("\t user: " + user.getName() + ", GUID: " + user.getGUID());
        }
        log();
    }

19.3.2.3 Code Sample 2

The following sample code illustrates how to create an application role and how to make a role a member of another role:

private void createAppRoles1() throws Exception {
        AppRoleManager arm1 = ap1.getAppRoleManager();
        log("----------------------------------------------------------");
        log("### Creating app roles in app policy1 with hierachy ###");
 
        AppRoleEntry sysAnalystRole =
            arm1.createAppRole(APP_ROLE_SYS_ANALYST, APP_ROLE_SYS_ANALYST,
                               APP_ROLE_SYS_ANALYST);
        AppRoleEntry sysDeveloperRole =
            arm1.createAppRole(APP_ROLE_SYS_DEVELOPER, APP_ROLE_SYS_DEVELOPER,
                               APP_ROLE_SYS_DEVELOPER);
        AppRoleEntry sysManagerRole =
            arm1.createAppRole(APP_ROLE_SYS_MANAGER, APP_ROLE_SYS_MANAGER,
                               APP_ROLE_SYS_MANAGER);
 
        ap1.addPrincipalToAppRole(sysManagerRole, APP_ROLE_SYS_DEVELOPER);
        ap1.addPrincipalToAppRole(sysDeveloperRole, APP_ROLE_SYS_ANALYST);
        log("### App roles in app policy #1 have been created ###");
        log();
 
    }

19.3.2.4 Code Sample 3

The following code sample illustrates several ways to query application roles:

private void queryAppRolesInApplicationPolicy1() throws Exception {
        AppRoleManager arm1 = ap1.getAppRoleManager();
 
        // Get role that matches a name
        AppRoleEntry are = arm1.getAppRole(APP_ROLE_SYS_MANAGER);
        log("----------------------------------------------------------");
        log("### Query app roles in application policy #1, by name ###");
        log("Found " + are.getName() + " by app role name.");
        log();
 
        // Get the role that matches a name exactly
        AppRoleSearchQuery q =
            new AppRoleSearchQuery(AppRoleSearchQuery.SEARCH_PROPERTY.NAME,
                                   false, ComparatorType.EQUALITY,
                                   APP_ROLE_SYS_ANALYST,
                                   AppRoleSearchQuery.MATCHER.EXACT);
        List<AppRoleEntry> arel = arm1.getAppRoles(q);
        log("### Query app roles in application policy #1, by exact query ###");
        log("Found " + arel.get(0).getName() + " by exact query.");
        log();
 
        // Get roles with names that begin with a given string
        q =
   new AppRoleSearchQuery(AppRoleSearchQuery.SEARCH_PROPERTY.NAME, false,
                          ComparatorType.EQUALITY,
                          APP_ROLE_SYS_DEVELOPER.subSequence(0, 7),
                          AppRoleSearchQuery.MATCHER.BEGINS_WITH);
        arel = arm1.getAppRoles(q);
        log("### Query app roles in app policy #1, by begins_with query ###");
        log("Found " + arel.get(0).getName() + " by begins_with query.");
        log();
 
        // Get roles with names that contain a given substring
        q =
   new AppRoleSearchQuery(AppRoleSearchQuery.SEARCH_PROPERTY.NAME, false,
                          ComparatorType.EQUALITY, "dummy",
                          AppRoleSearchQuery.MATCHER.ANY);
        arel = arm1.getAppRoles(q);
        log("### Query app roles in app policy #1, by matcher any ###");
        log("Found " + arel.size() + " app roles by matcher any.");
        for (AppRoleEntry ar : arel) {
            log("\t" + ar.getName());
        }
        log();
    }

19.3.2.5 Code Sample 4

The following sample illustrates how to map application roles to users and groups:

private void assignAppRoleToUsersAndGroups() throws Exception {
        // Obtain the user/group principals
        IdentityStore idmStore = idStore.getIdmStore();
        User tom = idmStore.searchUser(USER_TOM);
        User helen = idmStore.searchUser(USER_HELEN);
 
        Role trainingRole =
            idmStore.searchRole(IdentityStore.SEARCH_BY_NAME, GROUP_TRAINING);
        Role devRole =
            idmStore.searchRole(IdentityStore.SEARCH_BY_NAME, GROUP_DEV);
 
        Principal tomPrincipal =
            PrincipalFactory.getInstance().createWLSUser(tom.getName(),
                                                         tom.getGUID(),
                                                         tom.getUniqueName());
        Principal helenPrincipal =
            PrincipalFactory.getInstance().createWLSUser(helen.getName(),
                                                         helen.getGUID(),
                                                         helen.getUniqueName());
 
        Principal trainingPrincipal =
            PrincipalFactory.getInstance().createWLSGroup(trainingRole.getName(),
                                                          trainingRole.getGUID(),
                                                          trainingRole.getUniqueName());
        Principal devPrincipal =
            PrincipalFactory.getInstance().createWLSGroup(devRole.getName(),
                                                          devRole.getGUID(),
                                                          devRole.getUniqueName());
 
        // Application policy #1
        log("----------------------------------------------------------");
        log("### Assigning appl roles to users and groups, app policy #1 ###");
        ap1.addPrincipalToAppRole(helenPrincipal, APP_ROLE_SYS_MANAGER);
        ap1.addPrincipalToAppRole(devPrincipal, APP_ROLE_SYS_DEVELOPER);
 
        // Application policy #2
        log("### Assigning app roles to users and groups, app policy #2 ###");
        ap2.addPrincipalToAppRole(tomPrincipal, APP_ROLE_DIRECTOR);
        ap2.addPrincipalToAppRole(devPrincipal, APP_ROLE_INSTRUCTOR);
        ap2.addPrincipalToAppRole(trainingPrincipal, APP_ROLE_INSTRUCTOR);
 
        log("### App roles have been assigned to users and groups ###");
        log();
    }

19.3.2.6 Code Sample 5

The following code sample illustrates how to get all the roles that have a given user as a member:

private void showAppRoles() throws Exception {
        Subject tomSubject = getUserSubject(USER_TOM);
        Subject helenSubject = getUserSubject(USER_HELEN);
        Subject johnSubject = getUserSubject(USER_JOHN);
        Subject marySubject = getUserSubject(USER_MARY);
 
        Set<String> applications = new HashSet<String>();
        applications.add(APPLICATION_NAME1);
        applications.add(APPLICATION_NAME2);
 
        log("----------------------------------------------------------");
        log("### Query application roles for Tom ###");
        showAppRoles(applications, USER_TOM, tomSubject);
        log();
 
        log("### Query application roles for Helen ###");
        showAppRoles(applications, USER_HELEN, helenSubject);
        log();
 
        log("### Query application roles for John ###");
        showAppRoles(applications, USER_JOHN, johnSubject);
        log();
 
        log("### Query application roles for Mary ###");
        showAppRoles(applications, USER_MARY, marySubject);
        log();
    }

private Subject getUserSubject(String userName) throws Exception {
        Subject subject = new Subject();
 
        // Query users from ID store using user/role API,for user principal
        IdentityStore idmStore = idStore.getIdmStore();
        User user = idmStore.searchUser(userName);
 
        Principal userPrincipal =
            PrincipalFactory.getInstance().createWLSUser(user.getName(),
                                                         user.getGUID(),
                                                         user.getUniqueName());
 
        subject.getPrincipals().add(userPrincipal);
 
        // Query users from ID store using user/role API, for enterprise roles
        RoleManager rm = idmStore.getRoleManager();
        SearchResponse result = null;
        try {
            result = rm.getGrantedRoles(user.getPrincipal(), false);
        } catch (ObjectNotFoundException onfe) {
            // ignore
        }
 
        // Add group principals to the subject
        while (result != null && result.hasNext()) {
            Identity role = result.next();
            Principal groupPrincipal =
                PrincipalFactory.getInstance().createWLSGroup(role.getName(),
                                                              role.getGUID(),
                                                        role.getUniqueName());
            subject.getPrincipals().add(groupPrincipal);
        }
 
        // The subject now contains both user and group principals.
        // In the WebLogic Server, this setting is done by a login module
        return subject;
    }

private void showAppRoles(Set<String> applications, String user, Subject subject) {
        // Get all granted application roles for this subject
        Set<JpsApplicationRole> result = null;
        try {
            result = JpsAuth.getAllGrantedAppRoles(subject, applications);
        } catch (PolicyStoreException pse) {
            log(pse.toString());
        }
 
        if (result.size() <= 1) {
            log(user + " has " + result.size() + " application role.");
            if (result.size() == 1) {
                for (JpsApplicationRole ar : result) {
                    log("\tApplication role: " + ar.getName());
                }
            }
        } else {
            System.out.println(user + " has " + result.size() +
                               " application roles.");
            for (JpsApplicationRole ar : result) {
                log("\tApplication role: " + ar.getAppID() + "/" +
                    ar.getName());
            }
        }
    }

19.3.2.7 Code Sample 6

The following sample code illustrates how to remove the mapping of an application role to a group:

private void removeAppRoleForUserDirector() throws Exception {
        // Remove instructor role from Dev group
        log("----------------------------------------------------------");
        log("### Removing Instructor application role from Dev group ###");
 
        IdentityStore idmStore = idStore.getIdmStore();
        Role devRole =
            idmStore.searchRole(IdentityStore.SEARCH_BY_NAME, GROUP_DEV);
        Principal devPrincipal =
            PrincipalFactory.getInstance().createWLSGroup(devRole.getName(),
                                                          devRole.getGUID(),
                                                          devRole.getUniqueName());
 
        ap2.removePrincipalFromAppRole(devPrincipal, APP_ROLE_INSTRUCTOR);
        log("### Instructor app role has been removed from Dev group ###");
        log();
 
        log("----------------------------------------------------------");
        log("### Now query application roles for user John, again ###");
        Set<String> applications = new HashSet<String>();
        applications.add(APPLICATION_NAME1);
        applications.add(APPLICATION_NAME2);
 
        Subject johnSubject = getUserSubject(USER_JOHN);
        showAppRoles(applications, USER_JOHN, johnSubject);
        log();
    }

19.4 Appendix - Security Life Cycle of an ADF Application

This section explains the phases that the security of an application goes through. It is assumed that the application uses ADF and that it is developed in the Oracle JDeveloper environment.

The phases of the security life cycle of an application are the development phase, the deployment phase, and the management phase. The participants are the product manager or application architect, application developers, and application security administrators. For a summary of tasks, see Summary of Tasks per Participant per Phase.

19.4.1 Development Phase

In the development phase developers design the application to work with the full range of security options available in Oracle Fusion Middleware. Developers have access to a rich set of security services exposed by Oracle JDeveloper, the built-in ADF framework, and the Oracle WebLogic Server. All these components are based on OPSS, which ensures a consistent approach to security throughout the application's life span.

Typically, a developer uses the ADF Security Wizard (an authorization editor) and an expression language editor, all within Oracle JDeveloper; additionally and optionally, he may use OPSS APIs to implement more complex security tasks. Thus, some parts of the application use declarative security, others use programmatic security, and they both rely on security features available in the development and run-time environment.

Application developers also define a number of application entitlements and roles (policy seed data) required to secure the application. This policy seed data is kept in a source control system together with the application source code.

19.4.2 Deployment Phase

Once developed, the application is typically tested in a staging environment before being deployed to a production environment. In a production environment, both the application and the run-time services are integrated with other security components, such as user directories, single sign-on systems, user provisioning systems, and auditing. The security services usually change with the phase: for example, during development, a developer relies on a file or Oracle Wallet to store user credentials, but, in a production environment, credentials are stored in an LDAP directory (the OPSS security store).

In the deployment phase, typically, an administrator migrates the policy seed data to the production policy store (the OPSS security store), and maps application roles to enterprise groups to effect application security policies.

19.4.3 Management Phase

The management phase starts once an application has been deployed to a production environment. In this phase, application administrators or enterprise security administrators manage day-to-day security tasks, such as granting users access to application resources, reviewing audit logs, responding to security incidents, and applying security patches.

19.4.4 Summary of Tasks per Participant per Phase

The following tables summarize the major responsibilities per participant in each of the security life cycle phases and Figure 19-4 illustrates the basic flow.

Figure 19-4 Application Life Cycle Phases

Surrounding text describes Figure 19-4 .

Table 19-1 Security Tasks for the Application Architect

Phase Task

Development

Defines high-level application roles based on functional security and data security requirements.

Populates the initial file-based application policy store (jazn-data.xml).

Deployment

Defines real-world customer scenarios to be tested by the QA team.

Management

Understands and identifies the requirements to customize application policies.

Considers defining templates for vertical industries.


Table 19-2 Security Tasks for the Application Developer

Phase Task

Development

Uses tools and processes, specifically Oracle JDeveloper, to build the application and to create security artifacts, such as application roles and permissions.

Uses FND Grants to specify data-level security.

Tests the application using a local policy store with sample users and roles.

Deployment

Assists the QA team to troubleshoot and resolve runtime issues.


Table 19-3 Security Tasks for the Application Security Administrator

Phase Task

Deployment

Uses deployment services to migrate security seed data in jazn-data.xml to the production policy store.

Maps application roles to enterprise groups so that security policies can be enforced.

Management

Applies patches and upgrades software, as necessary.

Manages users and roles, as enterprise users and the application role hierarchy changes overtime.

Manages policies packed with the application and creates new ones.

Integrates with and manages the IAM infrastructure.


19.5 Appendix - Code and Configuration Examples

This section lists most of the code and configuration samples found elsewhere in this Guide, and a fully-written code example.

19.5.1 Code Examples

The following list includes typical security-related programming tasks and links to sample code illustrating implementations:

19.5.2 Configuration Examples

The following list includes typical security-related configuration tasks and links to sample configuration:

19.5.3 Full Code Example of a Java EE Application with Integrated Security

ezshare is a full example of a Java EE application whose security has been integrated with OPSS that uses permission-based grants and available at the Oracle Network. To locate the example, search for the keyword ezshare.