Programming Security For Java Applications

     Previous  Next    Open TOC in new window    View as PDF - New Window  Get Adobe Reader - New Window
Content starts here

Developing Applications Using the Java Security Service Module

The following topics are discussed in this section:

 


Overview of the Application Programming Steps

To use the Java SSM to design and develop of an Java application, perform the following steps (see Figure 6-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 SSM Application. For instructions on how to perform this task, see Writing Java SSM Applications.
  7. Figure 6-1 Java SSM Application Development Process


    Java SSM 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.

 


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
  2. 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.

  3. Use the AppContext interface to implement the collection of names and values.
  4. Structure your resources.
  5. 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 SSM 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:

 


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:
  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 6-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 6-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 6-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:

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

To register your naming authority class programmatically, fetch an instance of the Naming Authority Manager from the Java SSM 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.

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 SSM Applications

This section covers the following topics:

Knowledge Required of the Java SSM 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 assertion 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 SSM code examples provided in this document assume that the Security providers supplied with the product are configured in the Java SSM environment.

Writing an Authentication Application

This section covers the following topics:

Step-By-Step Procedure for Writing an Authentication Application

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

Figure 6-2 Developing a Java SSM Authentication Application

Developing a Java SSM 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 6-2).
  2. Listing 6-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";
  3. Write initialization code to initialize the configuration of the application and to initialize the Java SSM runtime to get an instance of it (see Listing 6-3).
  4. Listing 6-3 Application Configuration and Java SSM 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");
  5. Write code to get the policy domain from the Java SSM runtime (see Listing 6-4).
  6. Listing 6-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");
  7. Write code to get the Authentication Service from the policy domain (see Listing 6-5).
  8. Listing 6-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");
  9. Optional: Write code to check the service type to make sure that it is an Authentication Service (see Listing 6-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.
  10. Listing 6-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...
  11. Write code to authenticate the user (see Listing 6-7).
  12. Listing 6-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() );
  13. Write code that creates an AuthenticationHandler class that implements javax.security.auth.callback.CallbackHandler interface (see Listing 6-8). This class loops through the callbacks, prompts the user for the appropriate input to gather credentials, and fills in the username and password.
  14. Listing 6-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 );
    }
               }
           }
    }
  15. Write code that creates an input class to handle user input (see Listing 6-9).
  16. Listing 6-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

The assertIdentity() method is used to establish an identity for a user through identify assertion. The token-type name passed into the SSM 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 6-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 6-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 6-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 6-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 6-12). This method returns a true or false.

Listing 6-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

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

Figure 6-3 Developing a SSM Authorization Application

Developing a SSM 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 6-2, Policy Domain Specification Code, on page 6-11.
  2. Write initialization code to initialize the configuration of the application and to initialize the SSM to get an instance of it. For a code fragment that shows how to program this step, see Listing 6-3, Application Configuration and Java SSM Initialization Code, on page 6-12.
  3. Write code to get the policy domain from the Java SSM. For a code fragment that shows how to program this step, see Listing 6-4, Get Policy Domain Code, on page 6-12.
  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 6-5, Get the Authentication Service Code, on page 6-13.
  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 6-6, Authentication Service Type, Version, and isCompatible Code, on page 6-13.
  6. Write code to authenticate the user. For a code fragment that shows how to program this step, see Listing 6-7, User Authentication Code, on page 6-15.
  7. Write code to get the Authorization Service from the policy domain (see Listing 6-13).
  8. Listing 6-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");
  9. 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 6-6, Authentication Service Type, Version, and isCompatible Code, on page 6-13 and substitute Authorization for Authentication wherever references to the AuthenticationService occur.
  10. 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 6-14).
  11. Listing 6-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: ");
  12. Write code to create the RuntimeAction object and output the parsed resource for user confirmation. In Listing 6-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.
  13. Listing 6-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() );
    }
  14. 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 6-8, Authentication Handler Code, on page 6-16.
  15. Create an input class to handle user input. For a code fragment that shows how to program this step, see Listing 6-9, User Input Class Code, on page 6-17.

AuthorizationService.isAuthenticationRequired Method

The com.bea.security.AuthorizationService.isAuthenticationRequired() method is used in developing authorization applications. Listing 6-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 6-15, Action Object Code, on page 6-25.

Listing 6-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 6-4):

Figure 6-4 Developing a Java SSM Auditing Application

Developing a Java SSM 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 6-2, Policy Domain Specification Code, on page 6-11.
  2. Write initialization code to initialize the configuration of the application and to initialize the Java SSM to get an instance of it. For a code fragment that shows how to program this step, see Listing 6-3, Application Configuration and Java SSM Initialization Code, on page 6-12.
  3. Write code to get the policy domain from the Java SSM. For a code fragment that shows how to program this step, see Listing 6-4, Get Policy Domain Code, on page 6-12.
  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 6-17).
  5. Listing 6-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 );
  6. 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 6-6, Authentication Service Type, Version, and isCompatible Code, on page 6-13 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 6-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 6-5):

Figure 6-5 Developing a Java SSM Role Service Application

Developing a Java SSM 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 6-2, Policy Domain Specification Code, on page 6-11.
  2. Write initialization code to initialize the configuration of the application and to initialize the Java SSM to get an instance of it. For a code fragment that shows how to program this step, see Listing 6-3, Application Configuration and Java SSM Initialization Code, on page 6-12.
  3. Write code to get the policy domain from the Java SSM. For a code fragment that shows how to program this step, see Listing 6-4, Get Policy Domain Code, on page 6-12.
  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 6-5, Get the Authentication Service Code, on page 6-13.
  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 6-6, Authentication Service Type, Version, and isCompatible Code, on page 6-13.
  6. Write code to authenticate the user. For a code fragment that shows how to program this step, see Listing 6-7, User Authentication Code, on page 6-15.
  7. Write code to get the Role Service from the policy domain (see Listing 6-18).
  8. Listing 6-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");
  9. 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 6-6, Authentication Service Type, Version, and isCompatible Code, on page 6-13 and substitute Role for Authentication wherever references to the AuthenticationService occur.
  10. Write code to determine the roles of the authenticated user that is accessing the designated URL (see Listing 6-19).
  11. Listing 6-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 6-6):

Figure 6-6 Developing a Java SSM Credential Mapping Application

Developing a Java SSM 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 6-2, Policy Domain Specification Code, on page 6-11.
  2. Write initialization code to initialize the configuration of the application and to initialize the Java SSM to get an instance of it. For a code fragment that shows how to program this step, see Listing 6-3, Application Configuration and Java SSM Initialization Code, on page 6-12.
  3. Write code to get the policy domain from the Java SSM. For a code fragment that shows how to program this step, see Listing 6-4, Get Policy Domain Code, on page 6-12.
  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 6-5, Get the Authentication Service Code, on page 6-13.
  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 6-6, Authentication Service Type, Version, and isCompatible Code, on page 6-13.
  6. Write code to authenticate the user. For a code fragment that shows how to program this step, see Listing 6-7, User Authentication Code, on page 6-15.
  7. Write code to get the CredentailMapping Service from the policy domain (see Listing 6-20).
  8. Listing 6-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");
  9. 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 6-6, Authentication Service Type, Version, and isCompatible Code, on page 6-13 and substitute CredentialMapping for Authentication wherever references to the AuthenticationService occur.
  10. Write code to retrieve the credentials for the authenticate user that is accessing the designated URL (see Listing 6-21).
  11. Listing 6-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.
    ...
    }
    }
    }

  Back to Top       Previous  Next