Skip navigation.
Downloads | Product Documentation | Support

Programming Security For Java Applications

# Developing Applications Using the Java Security Service Module

The following topics are discussed in this section:

- Overview of the Application Programming Steps
- Choosing an Application Programming Model
- Defining the Application Context and Structure
- Defining and Specifying Naming Conventions
- Defining and Implementing a Naming Authority
- Registering a New Naming Authority
- Writing Java Security Service Module Applications

# Overview of the Application Programming Steps

To use the Java Security Service Module to design and develop of an Java application, perform the following steps (see Figure 5-1):

1. Choose an application programming model. For instructions on how to perform this task, see Choosing an Application Programming Model.
2. Define and specify the application context and structure. For instructions on how to perform this task, see Defining the Application Context and Structure.
3. Define and specify the naming conventions for all named objects. For instructions on how to perform this task, see Defining and Specifying Naming Conventions.
4. Design and implement a naming authority. For instructions on how to perform this task, see Defining and Implementing a Naming Authority.
5. Register the naming authority. For instructions on how to perform this task, see Registering a New Naming Authority.
6. Write the Java Security Service Module Application. For instructions on how to perform this task, see Writing Java Security Service Module Applications.

Figure 5-1 Java Security Service Module Application Development Process

# Choosing an Application Programming Model

When you develop your application, you have a choice of two different programming models: an open model or a closed model.

If an application conforms to the closed model, when a user attempts to use your application, the application responds by querying the user to find out who they are and then authenticates them. From that point forward, the application always knows the user identity. Thus, the application is closed in the sense that once the user is authenticated, their identity is established and rigid rules can then be enforced. The application uses that user identity for that user until the user logs out of the application. If an application conforms to the open model, the application only asks who the user is when there is a need to know.

The difference between the two models is that in the closed model, the application immediately does user authentication and never has to call the `com.bea.security.AuthorizationService.isAuthenticationRequired()` method on behalf of the user to determine whether a requested resource is protected. The application simply uses the identity of the user to call the `com.bea.security.AuthorizationService.isAccessAllowed()` method to determine if the authenticated user has the privileges required to access to resource.

In the open model, however, every time the unauthenticated user requests access to a resource, the application must call the `isAuthenticationRequired()` method. If the method returns `False` indicating that the resource does not require the application to authenticate users, the application allows the user to access it—the user is a guest and the resource is open to the public. If the `isAuthenticationRequired()` method returns `True`, then the application must authenticate the user to find out who they are and then call the `com.bea.security.AuthorizationService.isAccessAllowed()` method on behalf of the user to determine if the authenticated user has the privileges required to access the requested resource.

Both programming models are valid. The model you choose depends upon the nature of your application. The following scenarios describes typical of each type of programming model, open and closed.

- Open Programming Model Scenario—A newspaper web site is an example of an application in which you would use the open programming model. When users access the site, they are allowed to look at current news stories from the most recent issue of the newspaper without being asked to authenticate, or login. This is because access to current news stories is available to the public. However, if users request access to the newspaper archives, information to which access is restricted to subscribers only, they are prompted to supply credentials (such as a username and subscriber ID combination) so that they can be authenticated. Once authenticated, they are allowed to view the archives.
- Close Programming Model Scenario—A banking web site is an example of an application in which you would use the close programming model. When users access the site, they are immediately required to authenticate, or login. This way, no one can access any information on the site without authenticating first. Once users are authenticated, they are allowed to access, however, their access is restricted to viewing their accounts and performing transactions on their accounts. Only users who have special privileges, such as bank tellers, are allowed access to accounts other then their own.

# Defining the Application Context and Structure

An context of an application is the environment within which the application functions. The context allows you to write rules that use elements in this context. The context includes a collection of names and values that you implement using the `AppContext` interface. Once the interfaces are implemented, you pass the resulting objects through to the security providers. The security providers can then query the interfaces as they interact with the application.

To define the applications context and structure, do the following:

1. Define the application context

The application context establishes the user environment. For example, for a user session, the context defines the information about the user that the application tracks such as time spent using the application and details about the user.

Business and security manages usually collaborate to write rules that are then used to define the collection of names and values implemented in the `AppContext` interface. For example, their could be a rule for granting users different levels of authorization based on their financial status and specifying the requirements for being granted each authorization level. Another rule could assign users certain capabilities based on their credentials as determined by a credential mapper. If the application detects that a user has asserted their identity from a SAML token, then the application can make a SAML artifact available to pass their identity on and obviate the need to re-authenticate themselves.

2. Use the `AppContext` interface to implement the collection of names and values.
3. Structure your resources.

It is beneficial to create a hierarchy of resources so that resources have a parent to child relationship. This allows you to write rules to take advantage of inheritance. One example of this is having layers of forms in an Administration Application. In this case, you may have a series of items such as `Console.FORMNAME.menu.dropdown.menuitem`, `Console.FORMNAME.body.fieldname`, `Console.FORMNAME.body.header.fieldname`, and so on. By segmenting your application into these related hierarchical names, rules can be applied to the parent `(Console.FORMNAME`) or a child of the parent (`Console.FORMNAME.body`), allowing for a rule exception model.

# Defining and Specifying Naming Conventions

There are four types of named objects used in Java Security Service Module applications: `actions`, `auditRecords`, `ContextAuditRecord`, and `resources`. Because named objects conform to naming conventions, the security providers can look up their structure in the naming authority.

You must make decisions about the naming conventions to use for these objects and the naming authorities that are used to define and control the structure of their names. Some specific questions that you need to answer about named objects are as follows:

- How am I going to name my resources? Which naming scheme do I use?

URL is an example of a naming scheme.

- What does a name consist of?
- Will names use colons or slashes as delimiters?
- Will I use sub-names so as to allow a resource name to contain other names?
- How will I implement the naming authority? Will the application use the pre-configured URLBASE naming library that is provided with the Java Security Service Module?
- How will I load the naming authority XML format?

# Defining and Implementing a Naming Authority

To design and implement a naming authority, perform the following steps:

1. Pick a name for the naming authority and make a decisions on the naming authority delimiter, attributes, sub-authorities, and dependencies.
2. Decide which mechanism to use to define the naming authority. You have a choice of three mechanisms, as follows:

- Use the `DataDrivenAuthority` base class. For instructions on using this mechanism, see Using the DataDrivenAuthority Class on page 5-6.
- Use an XML file. For instructions on using this mechanism, see Using a DataDrivenAuthority XML File on page 5-6.
- Create a custom naming authority class. For instructions on using this mechanism, see Creating a Custom Naming Authority Class from the NamingAuthority Base Class on page 5-7.

3. Register the naming authority with the Naming Authority Manager. For instructions on registering the naming authority, see Registering a New Naming Authority on page 5-7.

## Using the DataDrivenAuthority Class

The `com.bea.security.DataDrivenAuthority` class provides a programmatic way to define a naming authority. By giving the `DataDrivenAuthority` class a name and adding attributes, delimiters, dependencies, and sub-authorities, you can define new naming conventions and construct a fully functional naming authority.

## Using a DataDrivenAuthority XML File

You can use an XML file to define a name authority within an XML document so that the Naming Authority Manager constructs your naming authority for you. The XML file shown in Listing 5-1 illustrates an example of a XML file that can be loaded into the Naming Authority Manager to automatically build instances of a `DataDrivenAuthority` class to govern naming systems.

Listing 5-1 DataDrivenAuthority XML File

>     <?xml version="1.0"?>
>     <AuthorityConfig>
>        <!-- *** Comment *** -->
>        <AuthorityDefinition name="NAME" delimiters=":">
>           <Dependencies>
>               <Authority name="OTHERAUTH"/>
>               <Authority name="YETANOTHERAUTH"/>
>           </Dependencies>
>           <Attribute name="singlename" type="SINGLE_VALUE_PREFIX"/>
>           <Attribute name="multiname" type="MULTI_VALUE_TERMINAL"
>                       authority="NAME:SUB"/>
>           <!-- *** Another Comment *** -->
>           <AuthorityDefinition name="NAME:SUB" delimiters="&amp;">
>              <Attribute name="singleterm" type="SINGLE_VALUE_TERMINAL"/>
>              <Attribute name="multiterm" type="MULTI_VALUE_TERMINAL"/>
>           </AuthorityDefinition>
>        </AuthorityDefinition>
>        <!-- *** Yet Another Comment *** -->
>        <AuthorityDefinition class="com.my.packagename.MyAuthority"/>
>     </AuthorityConfig>

In this example, the embedded `AuthorityDefinition` tags define sub-authorities. However, sub-authority names are still manually named to provide flexibility. Also, there is a direct reference to a class in the `CLASSPATH` with a simple `class="classname"` in an `AuthorityDefinition` tag. This class must base the `com.bea.security.NamingAuthority` class.

## Creating a Custom Naming Authority Class from the NamingAuthority Base Class

You may create a custom class that is derived from the `com.bea.security.NamingAuthority` base class. You can use this custom class to override the methods of the base class and provide custom or optimized parsing.

Only consider creating a custom naming authority class if one of the following scenarios applies:

- If the naming structure is so complicated that it is difficult to represent using the standard attributes and functions of the base class.
- If the naming structure is so complicated that there are time issues with using the standard parsing methods.

Note: If you decide to create a custom naming authority class, there are several functions that you can choose to implement in Java code rather than use the recursive authority/sub-authority mechanism used by the naming authority base class.

# Registering a New Naming Authority

Before your Java application can use a new naming authority, you must register the naming authority with the Naming Authority Manager.

When a naming authority is registered, all sub-authorities that it references are also registered. In addition, all naming authorities and sub-authorities are validated to ensure that they have proper attribute definitions and that their dependencies are satisfied. If each naming authority has a proper attribute configuration and its dependencies are met, it is tagged as validated and can be retrieved from the Naming Authority Manager for use.

If a naming authority does not pass validation, it is marked as invalid. Java applications cannot retrieve invalid naming authorities from the Naming Authority Manager. Every time a new naming authority is registered with the Naming Authority Manager, all invalid naming authorities are re-evaluated for dependencies and marked as valid if their dependencies are met.

The procedure you use to register a naming authority with the Naming Authority Manager differs depending on whether you are using a naming authority class or an XML file to define your naming authority. The following topics describe the different procedures:

- Using a Naming Authority Class on page 5-8.
- Using an XML file on page 5-8.
- Using a DataDrivenAuthority Object on page 5-9.

## Using a Naming Authority Class

To register your naming authority class programmatically, fetch an instance of the Naming Authority Manager from the Java Security Service Module and pass your naming authority in using the `com.bea.security.NamingAuthorityManager.registerAuthority` method. If the Naming Authority Manager contains an existing naming authority with the same name as the one you are registering, the existing naming authority is replaced by the newly registered naming authority, provided the new naming authority validates.

## Using an XML file

If you defined your naming authority in an XML file, use either of the following methods to register it.

- Method 1: Register the XML file with your application configuration object, `AppConfig`, so that when the `AppConfig` object is passed in to your application during Java Security Service Module initialization, the XML file is loaded.
- Method 2: Call the `com.bea.security.NamingAuthorityManager.loadXMLAuthorityDefinition()` method and pass in the name of the XML file to the Naming Authority Manager.
- The Naming Authority Manager reads the file and creates an instance of the `DataDrivenAuthority` object and registers it.

## Using a DataDrivenAuthority Object

To register a naming authority using a `DataDrivenAuthority` object, programmatically construct a `DataDrivenAuthority` object, passing in a name, delimiters, attributes, sub-authorities, and dependencies, and then register that object with the Naming Authority Manager using the `com.bea.security.NamingAuthorityManager.registerAuthority()` method.

# Writing Java Security Service Module Applications

This section covers the following topics:

- Knowledge Required of the Java Security Service Module Environment on page 5-9
- Writing an Authentication Application on page 5-10
- Writing an Authorization Application on page 5-21
- Writing an Auditing Application on page 5-26
- Writing a Role Service Application on page 5-28
- Writing a Credential Mapping Application on page 5-31

## Knowledge Required of the Java Security Service Module Environment

For the vast majority of security functions, you do not have to know about the configuration and capabilities of security providers. However, there are some functions that require that you know what the providers pass in and there is no way to query the security providers and have them tell you about themselves.The security providers pass objects as Java objects, so you must decide how to cast the object. For example, the object that you use to assert identity is determined by the identity asserter provider configured for your environment. If you have a SAML identity assertion provider configured, then it expects a SAML identity object to be passed in. The same is true with the Credential Mapper. A Credential Mapper defines two types of credentials that it passes, but the type received by the Credential Mapper really depends upon the type of Credential Mapping Provider configured. The credential is passed in as an object so you have to know if you asked for a credential. For example, an Oracle database password Credential Mapping Provider passes in password credential objects. The same consideration applies to Authentication Providers. The Java Authentication and Authorization Service (JAAS) defines six callback types. However, you can create an Authentication Provider that provides a custom callback that deviates from the standard.

Note: The Java Security Service Module code examples provided in this document assume that the Security providers supplied with the product are configured in the Java Security Service Module environment.

## Writing an Authentication Application

This section covers the following topics:

- Step-By-Step Procedure for Writing an Authentication Application
- Other AuthenticationService Methods

### Step-By-Step Procedure for Writing an Authentication Application

To write an authentication application, perform the following steps (see Figure 5-2):

Figure 5-2 Developing a Java Security Service Module Authentication Application

1. Write code to specify the configuration name and the policy domain. The configuration is created and named in the Administration Application. Note that a policy domain shares the same name as the configuration used to create it. (see Listing 5-2).

Listing 5-2 Policy Domain Specification Code

>          // The configuration name to use.
>          public static final String CONFIGNAME = "policydomain";

>          // The policy domain shares the same name as its configuration.
>          // The policy domain name to use.
>         public static final String POLICYDOMAIN = "policydomain";

1. Write initialization code to initialize the configuration of the application and to initialize the Java Security Service Module runtime to get an instance of it (see Listing 5-3).

Listing 5-3 Application Configuration and Java Security Service Module Initialization Code

>     // Initialize this applications configuration.
>     AppConfig cfg = new AppConfig();
>     // Policydomains are named after their configurations.
>             cfg.useConfiguration( CONFIGNAME );
>     // Initialize the security runtime.
>             try {
>                 SecurityRuntime.initialize( cfg );
>             }
>             catch( ParameterException pExc ) {
>                 // An error occurred with our configuration.
>                 System.out.println( pExc.getLocalizedMessage() );
>                 System.exit(pExc.hashCode());
>             }
>     // Get an instance of the runtime
>             SecurityRuntime rt = SecurityRuntime.getInstance();
>             System.out.println("Security Runtime Initialized");

1. Write code to get the policy domain from the Java Security Service Module runtime (see Listing 5-4).

Listing 5-4 Get Policy Domain Code

>            // Fetch the policy domain from the runtime.

>            PolicyDomain pd = null;
>            try {
>                 pd = rt.getPolicyDomain( POLICYDOMAIN );
>            }
>            catch( ParameterException pExc ) {
>                 // We could not get the policy domain.
>                 System.out.println( pExc.getLocalizedMessage() );
>                 System.exit(pExc.hashCode());
>            }
>            System.out.println("Retrieved Policy Domain");

1. Write code to get the Authentication Service from the policy domain (see Listing 5-5).

Listing 5-5 Get the Authentication Service Code

>     // Get the authentication service from the policy domain.
>            AuthenticationService atnSvc = null;
>            try {
>                 atnSvc = (AuthenticationService) pd.getService(
>                                                   ServiceType.AUTHENTICATION  );
>            }
>            catch( ServiceNotAvailableException naExc ) {
>                 // We could not fetch the service.
>                 System.out.println( naExc.getLocalizedMessage() );
>                 System.exit( naExc.hashCode() );
>            }
>            System.out.println("Retrieved Authentication Service");

1. Optional: Write code to check the service type to make sure that it is an Authentication Service (see Listing 5-6). If there are multiple versions of the Authentication Service available, you may also write code to check the version of the Authentication Service and verify that the version is compatible with the authentication application.

Listing 5-6 Authentication Service Type, Version, and isCompatible Code

>     // Validate that the service we retrieve is the type and level of
>     // compatibility we need.
>     // Get the policy domain.
>     PolicyDomain pd = null;
>     try {
>         pd = rt.getPolicyDomain( "POLICYDOMAIN" );
>     }
>     catch( ParameterException pExc ) {
>         System.err.println( pExc.getMessage() );
>         System.exit(-10);
>     }

>     // Get the authentication service.
>     PublicSecurityService myService = null;

>     try {
>         myService = pd.getService( ServiceType.AUTHENTICATION );
>     }
>     catch( ServiceNotAvailableException svcExc ) {
>         System.err.println(svcExc.getMessage());
>         System.exit(-10);
>     }

>     // Lets make sure that what is returned is an authentication
>     // service.

>     ServiceType sType = myService.getServiceType();

>     if ( sType != ServiceType.AUTHENTICATION ) {
>        System.err.println("We did not receive an authentication service!");
>        System.exit(-10);
>     }

>     // Lets make sure this service is compatible with the version we are coding
>     // against - version 1.0.

>     ServiceVersion expectedVersion = new ServiceVersion( 1, 0 );

>     int compatiblity_flag = myService.isCompatible( expectedVersion );

>     if ( compatibility_flag == PublicSecurityService.COMPATIBLE ) {
>        // This service is fully compatible with this application
>        // proceed with initialization.
>     } else if ( compatibility_flag ==
>     PublicSecurityService.COMPATIBLE_DEPRECATED ) {
>        // This service is fully compatible with this application
>        // except some functions will be changing in upcoming versions (some
>        // functions have been deprecated between versions).
>        // Warn the developers in a log file
>        log_warning("Authentication Service may use deprecated methods in version
>                                  " + myService.getVersion() )
>     } else if ( compatibility_flag == PublicSecurityService
>                                             .COMPATIBLE_UNKNOWN)
>     {
>        // The compatibility of this service is unknown. Usually because we
>        // expect a larger service version than what is currently installed.
>        // Compatibility may be assumed (you can try it)
>        // or you may choose to fail on unknown. We will warn the user
>        popup_warning("Authentication Service expects version " + expectedVersion
>     + " and got version " + myService.getVersion());
>     } else if ( compatibility_flass == PublicSecurityService.NOT_COMPATIBLE ) {
>        // This service is known not to be compatible with the version expected.
>        // Stop initialization and exit this application
>        popup_warning("Authentication Service version " + myService.getVersion()
>                               + " is not compatible with this application" );
>        System.exit(-20);
>     }

>     // Continue with application initialization...

1. Write code to authenticate the user (see Listing 5-7).

Listing 5-7 User Authentication Code

>             // Start authentication
>             AuthenticIdentity ident=null;

>             try {
>                ident = atnSvc.authenticate( new AuthenticationHandler() );
>             }
>             catch( IdentityNotAuthenticException naExc ) {
>                System.out.println( naExc.getLocalizedMessage() );
>                System.exit( naExc.hashCode() );
>             }

>             System.out.println("Authentication Succeeded");
>             System.out.println( ident.toString() );

1. Write code that creates an `AuthenticationHandler` class that implements `javax.security.auth.callback.CallbackHandler` interface (see Listing 5-8). This class loops through the callbacks, prompts the user for the appropriate input to gather credentials, and fills in the username and password.

Listing 5-8 Authentication Handler Code

>         public static class AuthenticationHandler implements
>              javax.security.auth.callback.CallbackHandler {

>            protected String username = null;
>            protected char[] password = null;

>            public String getPassword() {
>                 return new String( password );
>            }

>            public String getUsername() {
>                 return username;
>            }

>            public AuthenticationHandler( ) {
>            }

>            public AuthenticationHandler( String username, String password ) {
>                this.username = username;
>                this.password = password.toCharArray();
>            }

>            public void handle(Callback[] callbacks) throws IOException,
>                             UnsupportedCallbackException {

>               // Loop through the callbacks and prompt the user with the
>                         appropriate input to gather credentials

>                 for ( int numcb=0; numcb < callbacks.length; numcb++ ) {

>                     // Fill in the username
>                   if ( callbacks[numcb] instanceof
>                            javax.security.auth.callback.NameCallback ) {
>                    javax.security.auth.callback.NameCallback ncb = (
>                     javax.security.auth.callback.NameCallback ) callbacks[numcb];

>                    if ( username == null ) {
>                    // Fetch the username from the user
>                     username = Input.getString( ncb.getPrompt() );
>                     ncb.setName( username );
>                      } else {
>                       ncb.setName( username );
>                       }
>                    }

>                    // Fill in the password
>                    if ( callbacks[numcb] instanceof
>                     javax.security.auth.callback.PasswordCallback ) {
>                        javax.security.auth.callback.PasswordCallback pcb = (
>                             javax.security.auth.callback.PasswordCallback )
>                                       callbacks[numcb];

>                         if ( password == null ) {
>                         String pwd = Input.getString( pcb.getPrompt() );
>                         password = pwd.toCharArray();
>                         }
>                          pcb.setPassword( password );
>                      }

>                }

>            }
>         }

1. Write code that creates an input class to handle user input (see Listing 5-9).

Listing 5-9 User Input Class Code

>         public static class Input {
>            public static String getString( String prompt ) {

>                 BufferedReader stdin = new BufferedReader( new InputStreamReader(
>                                                            System.in ) );
>                System.out.print( prompt );
>                System.out.flush();
>                String input = null;
>                try {
>                  input = stdin.readLine();
>                }
>                catch( IOException ioExc ) {
>                     System.out.println( ioExc.getLocalizedMessage() );
>                }
>                 if ( input == null ) {
>                     return "";
>                 } else {
>                     return input;
>                 }
>              }

>         }

### Other AuthenticationService Methods

The following `com.bea.security.AuthenticationService` class methods are also available for use in developing authentication applications:

- assertIdentity Method
- getChallengeAsssertionToken Method
- isAssertionTokenSupported Method

#### assertIdentity Method

The `assertIdentity()` method is used to establish an identity for a user through identify assertion. The token-type name passed into the Security Service Module must be supported by a provider or an exception is thrown. The object reference must implement an interface known to the token provider and must be a valid token or else an exception is thrown. If these requirements are met, this method returns an authenticated identity.

The format of the token is up to the Identity Assertion Provider that handles that token type In Listing 5-10, the token is a certificate and the token type is X.509. Therefore, to assert identity so as to satisfy the requirements noted in the previous paragraph, an application developer must understand the format of the token he passes in.

Listing 5-10 assertIdentity Method Code

>        // Get an X509 certificate from somewhere in my application.
>             AppCertificate certificate = myApp.getCertificate();
>             // Assert identity from the token.
>             AuthenticIdentity myUser = null;
>             try {
>                 myUser = authSvc.assertIdentity( "X509", certificate.getBytes() );
>             }
>             catch( IdentityNotAuthenticException inaExc  ) {
>                 // This exception is thrown if I am not allowed to assert
>                 // an identity from this token.
>                 System.err.println( inaExc.getMessage());
>             }
>             catch( InvalidAssertionTokenException inatExc ) {
>               // This exception is thrown if the token type X509 is not
>               // understood by the providers or if the token format is invalid.
>                 System.err.println( inaExc.getMessage());
>             }

#### getChallengeAsssertionToken Method

The `getChallengeAsssertionToken()` method returns an identity assertion token that contains a challenge that needs a response from the application before asserting the identity (see Listing 5-11). If the token type requested is not a challenge token type, an exception is thrown. This method returns an object reference with an interface type appropriate to the token type requested and needs to be cast to the appropriate type before it is used.

Listing 5-11 getChallengeAsssertionToken Method

>             // Get the SKey challenge object.
>             Object token = null;
>             try {
>                 token = authSvc.getChallengeAssertionToken("S/KEY");
>             }
>             catch( InvalidAssertionTokenException inatExc ) {
>                 // This exception is thrown if the providers do not know
>                 // about a challenge token format of "S/KEY".
>                 System.err.println( inatExc.getMessage() );
>                 System.exit(-10);
>             }

>             // Caste the challenge token to the correct format.
>             SKEYChallenge chal = (SKEYChallenge) token;

>             // Challenge the user and get the response.
>             String response = challengeUser( chal.getChallenge() );

>             // Fill in the challenge token
>             chal.setResponse( response );

>             // Assert identity with the challenge token.
>             AuthenticIdentity myUser = null;
>             try {
>                 myUser = authSvc.assertIdentity( "S/KEY", chal );
>             }
>             catch( IdentityNotAuthenticException inaExc  ) {
>                 // This exception is thrown if I am not allowed to assert
>                 // an identity from this token.
>                 System.err.println( inaExc.getMessage() );
>             }
>             catch( InvalidAssertionTokenException inatExc ) {
>               // This exception is thrown if the token type S/KEY is not
>               // understood by the providers or if the token format is invalid.
>                 System.err.println( inatExc.getMessage() );
>             }

#### isAssertionTokenSupported Method

This method identifies whether a specific token type, indicated by its unique name, is available for use within current policy domain (see Listing 5-12). This method returns a `true` or `false`.

Listing 5-12 IsAssertionTokenSupported Method Code

>       // Query if the "X509" assertion type is supported.
>             boolean isSupp = authSvc.isAssertionTokenSupported("X509");
>           if ( isSupp ) {
>             System.out.println("X509 assertion tokens are supported");
>           } else {
>             System.out.println("X509 assertion tokens are NOT supported");
>           }

## Writing an Authorization Application

This section covers the following topics:

- Step-by-Step Procedure for Writing an Authorization Application
- AuthorizationService.isAuthenticationRequired Method

### Step-by-Step Procedure for Writing an Authorization Application

To write an authorization application, perform the following steps (see Figure 5-3):

Figure 5-3 Developing a Security Service Module Authorization Application

1. Write code to specify the configuration name and the policy domain. The configuration is created and named in the Administration Application. Note that a policy domain shares the same name as the configuration used to create it. For a code fragment that shows how to program this step, see Listing 5-2.
2. Write initialization code to initialize the configuration of the application and to initialize the Security Service Module to get an instance of it. For a code fragment that shows how to program this step, see Listing 5-3.
3. Write code to get the policy domain from the Java Security Service Module. For a code fragment that shows how to program this step, see Listing 5-4.
4. Write code to get the Authentication Service from the policy domain. For a code fragment that shows how to program this step, see Listing 5-5.
5. Optional: Write code to check the service type to make sure that it is an Authentication Service. If there are multiple versions of the Authentication Service available, you may also write code to check the version of the Authentication Service and to verify that the version is compatible with the authorization application. For a code fragment that shows how to program this step, see Listing 5-6.
6. Write code to authenticate the user. For a code fragment that shows how to program this step, see Listing 5-7.
7. Write code to get the Authorization Service from the policy domain (see Listing 5-13).

Listing 5-13 Get Authorization Service Code

>             // Authentication complete - now authorize a resource.
>             // Get the authorization service from the policy domain.

>             AuthorizationService atzSvc = null;

>             try {

>                 atzSvc = (AuthorizationService) pd.getService(
>                                      ServiceType.AUTHORIZATION  );
>            }
>            catch( ServiceNotAvailableException naExc ) {
>                // We could not fetch the service
>                System.out.println( naExc.getLocalizedMessage() );
>                System.exit( naExc.hashCode() );
>            }
>            System.out.println("Retrieved Authorization Service");

1. Optional: Write code to check the service type to make sure that it is an Authorization Service. If there are multiple versions of the Authorization Service available, you may also write code to check the version of the Authorization Service and verify that the version is compatible with the authorization application. To program this step, use the code fragment shown in Listing 5-6 and substitute Authorization for Authentication wherever references to the AuthenticationService occur.
2. Write code to request a resource string in the format defined by naming authority, create the resource object, output the resource for user confirmation, and request an action string in the format defined by action authority (see Listing 5-14).

Listing 5-14 Request Resource String and Create Resource Object Code

>            // Output the resource string defined by the naming authority.

>            System.out.println("EXAMPLERESAUTHORITY is defined as:
>                servername:user@filename-fieldname (i.e.
>                             www:bob@index.html-searchinput )");

>             String resourcestring = Input.getString("Enter a resource string in
>                             the format defined by EXAMPLERESAUTHORITY: ");

>            // Create the resource object
>            RuntimeResource rResource = new RuntimeResource( resourcestring,
>                                               "EXAMPLERESAUTHORITY" );

>     System.out.println("EXAMPLEACTAUTHORITY is defined as:
>                                  mainaction:followup (i.e. GET:LOG)");
>            String actionstring = Input.getString("Enter an action string
>                                 in the format defined by EXAMPLEACTAUTHORITY: ");

1. Write code to create the `RuntimeAction` object and output the parsed resource for user confirmation. In Listing 5-15, note that the `isAccessAllowed()` method is used to determine whether the authenticated user (`identi`) is authorized to perform the requested `action` on the designated `resource`.

Listing 5-15 Action Object Code

>            // Create the action object.
>            RuntimeAction rAction = new RuntimeAction( actionstring,
>                                                 "EXAMPLEACTAUTHORITY" );

>            // Output the parsed action for user confirmation.

>     System.out.println("Authorizing user for this resource and action\n");

>            AccessResult rResult = null;
>            try {
>                 rResult = atzSvc.isAccessAllowed( ident , rResource, rAction );
>            }
>            catch( IdentityNotAuthenticException idExc ) {
>                System.out.println( idExc.getLocalizedMessage() );
>                System.exit( idExc.hashCode() );
>             }

>             // We got a valid result
>            System.out.println("Access Result:");
>            System.out.println("   Access Allowed: " + String.valueOf(
>                                   rResult.isAllowed() ) );
>            System.out.println("   Decision Time: " +
>                                    rResult.getDecisionTime().toString() );
>     }

1. Create an `AuthenticationHandler` class that implements `javax.security.auth.callback.CallbackHandler` interface. This class loops through the callbacks, prompts the user for the appropriate input to gather credentials, and fills in the username and password. For a code example that shows how to program this step, Listing 5-8.
2. Create an input class to handle user input. For a code fragment that shows how to program this step, see Listing 5-9.

### AuthorizationService.isAuthenticationRequired Method

The `com.bea.security.AuthorizationService`.`isAuthenticationRequired()` method is used in developing authorization applications. Listing 5-16 shows how to program `isAuthenticationRequired()` method. This method returns `true` or `false` to indicate whether an anonymous user is required to authenticate before accessing a resource and action. If this method returns `false`, user authentication is not required and no further access query needs to be performed. If this method returns `true`, then the application must authenticate the user and then call the `isAccessAllowed()` method on the AuthorizationService to get an access decision. For a code fragment that shows how to use the `isAccessAllowed()` method, see Listing 5-15.

Listing 5-16 isAuthenticationRequired Method

>     // Determine if authentication is required to access the URL
>     // http://www.bea.com/index.html via an HTTP GET.

>     // Create the resource.
>     RuntimeResource beaurl = new RuntimeResource(
>                           "http://www.bea.com/index.html" , "URL_AUTHORITY" );

>     // Create the action.
>     RuntimeAction action = new RuntimeAction( "GET", "SIMPLE_ACTION" );

>     // See if authentication is required.
>     boolean result = atzService.isAuthenticationRequired( beaurl, action );

>     if ( result == true ) {
>        // Authentication is required. I need to authenticate the user
>        // and then call isAccessAllowed on this authorization service
>        // before I can serve this URL to the user
>        ...
>     } else {
>        // Authentication is not required. I can allow this user to access this
>        // URL.
>        ...
>     }

## Writing an Auditing Application

This section provides a step-by-step procedure for writing an auditing application.

To write an auditing application, perform the following steps (see Figure 5-4):

Figure 5-4 Developing a Java Security Service Module Auditing Application

1. Write code to specify the configuration name and the policy domain. The configuration is created and named in the Administration Application. Note that a policy domain shares the same name as the configuration used to create it. For a code fragment that shows how to program this step, see Listing 5-2.
2. Write initialization code to initialize the configuration of the application and to initialize the Java Security Service Module to get an instance of it. For a code fragment that shows how to program this step, see Listing 5-3.
3. Write code to get the policy domain from the Java Security Service Module. For a code fragment that shows how to program this step, see Listing 5-4.
4. Write code that gets the Auditing Service from the policy domain, constructs an audit message, and creates the `AuditRecord` object to pass the auditing event to the security runtime (see Listing 5-17).

Listing 5-17 AuditingService Code

>            // Get the audting service.
>             PublicSecurityService myService = null;

>             try {
>                 myService = pd.getService( ServiceType.AUDIT );
>             }
>             catch( ServiceNotAvailableException svcExc ) {
>               // Exception is thrown if service is not present
>                 System.err.println(svcExc.getMessage());
>                 System.exit(-10);
>             }

>             AuditingService adtService = (AuditingService) myService;

>             // Create an audit record to determine it's naming authority,
>             // severity, and message.

>             AuditRecord adtRec = new AuditRecord("MyAppError", AuditRecord.ERROR,
>                                                     "This is an ERROR message");

>             // Record the audit record to the auditing service provider
>             adtService.recordEvent( adtRec );

1. Optional: Write code to check the service type to make sure that it is an Auditing Service. If there are multiple versions of the Auditing Service available, you may also write code to check the version of the Auditing Service and to verify that the version is compatible with the authorization application. To program this step, use the code fragment shown in Listing 5-6 and substitute Auditing for Authentication wherever references to the AuthenticationService occur. After writing this `type`, `version` and `iscompatible` code, insert it into code in Listing 5-17 just after the code that gets the Auditing Service.

## Writing a Role Service Application

You use the role service to allow the application to extract role information about specific identities and resources within the context of the application.

To write a Role Service application, perform the following steps (see Figure 5-5):

Figure 5-5 Developing a Java Security Service Module Role Service Application

1. Write code to specify the configuration name and the policy domain. The configuration is created and named in the Administration Application. Note that a policy domain shares the same name as the configuration used to create it. For a code fragment that shows how to program this step, see Listing 5-2.
2. Write initialization code to initialize the configuration of the application and to initialize the Java Security Service Module to get an instance of it. For a code fragment that shows how to program this step, see Listing 5-3.
3. Write code to get the policy domain from the Java Security Service Module. For a code fragment that shows how to program this step, see Listing 5-4.
4. Write code to get the Authentication Service from the policy domain. For a code fragment that shows how to program this step, see Listing 5-5.
5. Optional: Write code to check the service type to make sure that it is an Authentication Service. If there are multiple versions of the Authentication Service available, you may also write code to check the version of the Authentication Service and to verify that the version is compatible with the authorization application. For a code fragment that shows how to program this step, see Listing 5-6.
6. Write code to authenticate the user. For a code fragment that shows how to program this step, see Listing 5-7.
7. Write code to get the Role Service from the policy domain (see Listing 5-18).

Listing 5-18 Get the Role Service Code

>     // Get the role service from the policy domain
>            RoleService rmService = null;
>            try {
>                 rmService = (RoleService) pd.getService(
>                                                   ServiceType.ROLE  );
>            }
>            catch( ServiceNotAvailableException naExc ) {
>                 // We could not fetch the service
>                 System.out.println( naExc.getLocalizedMessage() );
>                 System.exit( naExc.hashCode() );
>            }
>            System.out.println("Retrieved Role Service");

1. Optional: Write code to check the service type to make sure that it is a Role Service. If there are multiple versions of the Role Service available, you may also write code to check the version of the Role Service and verify that the version is compatible with the Role Service application. To program this step, use the code fragment shown in Listing 5-6 and substitute Role for Authentication wherever references to the AuthenticationService occur.
2. Write code to determine the roles of the authenticated user that is accessing the designated URL (see Listing 5-19).

Listing 5-19 Get Roles Code

>             // Determine what roles myUser is in when accessing
>             // http://www.bea.com/index.html with a HTTP GET.
>             // Create the resource.
>             RuntimeResource beaurl = new RuntimeResource(
>                              "http://www.bea.com/index.html" , "URL_AUTHORITY" );

>             // Create the action.
>             RuntimeAction action = new RuntimeAction( "GET", "SIMPLE_ACTION" );

>             // Get a reference to the application context
>             AppContext ctx = MySession.getContext();

>             // Try fetching our roles
>             Vector roles=null;
>             try {
>                 roles = rmService.getRoles( myUser, beaurl,  action, ctx );
>             }
>             catch( IdentityNotAuthenticException identExc ) {
>               // Exception is thrown if myUser is not properly authenticated
>                 System.err.println( identExc.getMessage() );
>             }

>             if ( roles != null ) {
>               // Print the roles and descriptions
>                 for ( int loop=0; loop < roles.size(); loop++ ) {
>                     IdentityRole role = (IdentityRole) roles.elementAt( loop );
>                     System.out.println( role.getName() );
>                     System.out.println( role.getDescription() );
>                 }
>             }

## Writing a Credential Mapping Application

You use the credential mapping service to allow the application to fetch credentials of certain types associated with a specific identity for a specific resource. These credentials can then be used on behalf of that identity to provide some privileged function, such as to logging into a database, or sending mail.

To write a Credential Mapping Service application, perform the following steps (see Figure 5-6):

Figure 5-6 Developing a Java Security Service Module Credential Mapping Application

1. Write code to specify the configuration name and the policy domain. The configuration is created and named in the Administration Application. Note that a policy domain shares the same name as the configuration used to create it. For a code fragment that shows how to program this step, see Listing 5-2.
2. Write initialization code to initialize the configuration of the application and to initialize the Java Security Service Module to get an instance of it. For a code fragment that shows how to program this step, see Listing 5-3.
3. Write code to get the policy domain from the Java Security Service Module. For a code fragment that shows how to program this step, see Listing 5-4.
4. Write code to get the Authentication Service from the policy domain. For a code fragment that shows how to program this step, see Listing 5-5.
5. Optional: Write code to check the service type to make sure that it is an Authentication Service. If there are multiple versions of the Authentication Service available, you may also write code to check the version of the Authentication Service and to verify that the version is compatible with the authorization application. For a code fragment that shows how to program this step, see Listing 5-6.
6. Write code to authenticate the user. For a code fragment that shows how to program this step, see Listing 5-7.
7. Write code to get the CredentailMapping Service from the policy domain (see Listing 5-20).

Listing 5-20 Get the CredentialMapping Service Code

>     // Get the CredentialMapping service from the policy domain
>            RoleService rmService = null;
>            try {
>                 cmService = (CredentialMappingService) pd.getService(
>                                                   ServiceType.CredentialMapping  );
>            }
>            catch( ServiceNotAvailableException naExc ) {
>                 // We could not fetch the service
>                 System.out.println( naExc.getLocalizedMessage() );
>                 System.exit( naExc.hashCode() );
>            }
>            System.out.println("Retrieved CredentialMapping Service");

1. Optional: Write code to check the service type to make sure that it is a CredentialMapping Service. If there are multiple versions of the CredentialMapping Service available, you may also write code to check the version of the CredentialMapping Service and verify that the version is compatible with the CredentialMapping Service application. To program this step, use the code fragment shown in Listing 5-6 and substitute CredentialMapping for Authentication wherever references to the AuthenticationService occur.
2. Write code to retrieve the credentials for the authenticate user that is accessing the designated URL (see Listing 5-21).

Listing 5-21 Get Credentials Code

>           // Retrieve credentials for MyUser according to the current resource and
>         // action being accessed and from a list of credential types that I am
>         // interrested in.
>             // Create the resource.
>             RuntimeResource beaurl = new RuntimeResource(
>                        "http://www.bea.com/index.html" , "URL_AUTHORITY" );

>             // Create the action.
>             RuntimeAction action = new RuntimeAction( "GET", "SIMPLE_ACTION" );

>             // Try fetching the credentials.
>             String[] askingCreds = new String[2];
>             askingCreds[0] = "oracledb";
>             askingCreds[1] = "3desDecryptionKey";
>             Vector creds=null;
>             try {
>                 // Both byIdent and forIdent are the same since I am fetching these
>               // credentials for myself.
>                 creds = cmService.getCredentials( myUser, myUser, beaurl,  action,
>                                                    askingCreds );
>             }
>             catch( IdentityNotAuthenticException identExc ) {
>                 assertNull( identExc.getMessage(), identExc );
>             }
>             catch( ParameterException pExc ) {
>                 assertNull( pExc.getMessage(), pExc );
>             }

>             if ( creds != null ) {
>                 System.out.print("Returned " + String.valueOf( creds.size() ) +
>                                           "credential objects.");
>                 for ( int loop=0; loop < creds.size(); loop++ ) {
>                     Object cred = creds.elementAt( loop );

>                 // The type of objects returned depend on the credential type.
>                 // Either javax.resource.spi.security.PasswordCredential or
>                 // javax.resource.spi.security.GenericCredential are
>                 // recommended.
>                 // However, custom credential types are allowed.
>                     if ( cred instanceof
>                            javax.resource.spi.security.PasswordCredential ) {
>                       // This is a password credential.
>                   ...
>                 } else if ( cred instanceof
>                            javax.resource.spi.security.GenericCredential ) {
>                     // This is a generic credential.
>                       ...
>                 } else {
>                     // This is a custom credential type.
>                       ...
>                 }
>                 }
>             }