Skip Headers
Oracle® Fusion Middleware Developer's Guide for Oracle Adaptive Access Manager
Release 11g (11.1.1)

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

Go to previous page
Previous
Go to next page
Next
View PDF

9 OTP Anywhere

Oracle Adaptive Access Manager 11g provides the framework to support the One Time Password authentication method.

One Time Password (OTP) is used to authenticate an individual based on a single-use alphanumeric credential.

The OTP is delivered to the user's configured delivery method. The user then provides the OTP credential as the response to proceed with the operation.

The following are major benefits of using out-of-band OTP:

This chapter provides an example of how to integrate OTP into the system. It contains the following sections:

9.1 OTP Integration

To integrate OTP into your system, the following tasks must be performed:

  1. Implement a challenge processor.

  2. Configure the authentication device

  3. Configure the user information properties

9.2 Implementing Challenge Processors

Challenge Processors are a plug-in framework that allows integrators the ability to write custom processor classes that can be triggered when an associated rule action is returned by the challenge checkpoint.

Challenge processors perform the following tasks:

Processor classes are:

To use SMS, you must implement a method for generating the secret PIN and checking the status of the send and the class that is called for a challenge type. You must also configure policies to use SMS.

For instructions on customizing, extending, or overriding Oracle Adaptive Access Manager properties, refer to Chapter 12, "Customizing Oracle Adaptive Access Manager."

9.2.1 Create a Challenge Processor

To implement a challenge processor, you will need to extend the following class:

com.bharosa.uio.processor.challenge.AbstractChallengeProcessor 

Later, you will compile the code by adding oaam.jar from $ORACLE_IDM_HOME\oaam\cli\lib folder to the build classpath.

Methods to Implement

A few methods to implement a challenge processor is shown as follows:

protected boolean generateSecret(UIOSessionData sessionData, boolean isRetry) to generate code to send to client

protected boolean validateAnswer(UIOSessionData sessionData, String answer) to validate the user answer

public String checkDeliveryStatus(UIOSessionData sessionData, boolean userWaiting, boolean isRetry) if you want to provide wait until message is sent

public boolean isServiceAvailable(UIOSessionData sessionData) to check if external service is available

Example

An example of implementing a challenge processor is shown as follows:

package oracle.oaam.challenge.processor.challenge;
 
import com.bharosa.common.util.*;
import com.bharosa.uio.util.UIOUtil;
import com.bharosa.uio.util.UIOSessionData;
 
import com.bharosa.common.logger.Logger;
 
import java.io.Serializable;
 
/**
 * Email Challenge Processor - provides OTP Code generation, delivery and validation
 */
public class EmailChallengeProcessor extends com.bharosa.uio.processor.challenge.AbstractOTPChallengeProcessor implements Serializable{
 
  static Logger logger = Logger.getLogger(EmailChallengeProcessor.class);
 
  public EmailChallengeProcessor( ) {
  }
 
  /**
   * Generates OTP Code and stores it in sessionData
   * 
   * @param sessionData data object available for the session
   * @param isRetry boolean value if method was called as a result of a failed answer attempt
   * @return 
   */
  protected boolean generateSecret(UIOSessionData sessionData, boolean isRety) {
   String otpCode = sessionData.getOTPCode(); 
 
// If no secret code is present in session, generate one.
    if (StringUtil.isEmpty(otpCode)) {
      if (logger.isDebugEnabled())
        logger.debug("ChallengeEmail generating security code for user: " +
                     sessionData.getCustomerId());
      otpCode = generateCode(sessionData);
 
      // save the code for later reference - validate / resend
      sessionData.setOTPCode(otpCode);
    }
 
    if (logger.isDebugEnabled())
      logger.debug("OTP code for user " + sessionData.getCustomerId() + " : " + otpCode);
 
    if (StringUtil.isEmpty(otpCode)) {
      logger.error("Email Challenge pin generation returned null.");
      return false;
    }
        // isRetry flag is turned on if user fails to answer the question
    if (!isRetry) {       
      return sendCode(sessionData);
    }
    
    return true;
  }
 
  /**
   * Validate user entered answer against value in sessionData
   * 
   * @param sessionData validate code and return result.
   * @param answer answer provided by the user
   * @return
   */
  protected boolean validateAnswer(UIOSessionData sessionData, String answer){
    //need to authenticate OTP Code
    String otpCode = sessionData.getOTPCode();
    
    if (otpCode != null && otpCode.equals(answer)) {
      // Expire OTP Code
      sessionData.setOTPCode(null);
      return true;
    }
    
    return false;
  }
 
  /**
   * Private methods to send secret code to client
   * 
   * @param sessionData
   * @return
   */
  private boolean sendCode(UIOSessionData sessionData){
    String otpCode = sessionData.getOTPCode();
 
    try {
      // UIOUtil.getOTPContactInfo fetches the information registered by the user. Refer to ChallengeEmail.requiredInfo in configuration.
      String toAddr = UIOUtil.getOTPContactInfo(sessionData, "email");
      if (StringUtil.isEmpty(toAddr)) {
        logger.error("No user email in profile.");
         return false;  
      }
 
      // Send secret code to customer using your email provider
 
    } catch (Exception ex) {
        logger.error("ChallengeEmail Error sending code.", ex);
        return false;
    }
    
    return true;
  }
  
  public String checkStatus(UIOSessionData sessionData, boolean userWaiting, boolean isRetry) {
    String target = ChallengeProcessorIntf.TARGET_WAIT;
    // user already has code, trying again - send to challenge page
    if (isRetry){ 
      return ChallengeProcessorIntf.TARGET_CHALLENGE;
    }
    
    boolean sendComplete = false;
    if (userWaiting){
      // if secret code is sent set target to 
      target = ChallengeProcessorIntf.TARGET_CHALLENGE;
      // failed to send
      target = ChallengeProcessorIntf.TARGET_ERROR;
      // still processing    
      target = ChallengeProcessorIntf.TARGET_WAIT;   
    }    
    return target;
  }
}

9.2.2 Configure Custom Challenge Processor as Challenge Type with Required Profile Data

Challenge types are configured by the enum, "challenge.type.enum". The actual enum value is shown as follows:

bharosa.uio.<application>. challenge.type.enum.<challenge type>

Example for Defining an OTP Type

Configure the bharosa.uio.default.challenge.type.enum property to edit out of the box OTP challenge types or add a new challenge type.

Here is an example for defining an OTP type:

bharosa.uio.default.challenge.type.enum.MyChallenge

In the example, the "default" is the UIO application name, and "MyChallenge" is challenge Type being newly added

To enable/disable a challenge type, the available flag should be set (not the enable flag, that would remove it from list)

Table 9-1 Challenge type Properties

Property Description

available

if the challenge type is available for use (service ready and configured). To enable/disable an OTP challenge type, the available flag should be set.

processor

java class for handling challenges of this type.

requiredInfo

comma separated list of inputs from the registration input enum


Attributes of the enum with example values is shown as follows:

bharosa.uio.default.challenge.type.enum.MyChallenge = 1  // unique value to identify Challenge Email in bharosa.uio.default.challenge.type.enum

bharosa.uio.default.challenge.type.enum.MyChallenge.name = MyChallenge //  unique string to identify Challenge Email in bharosa.uio.default.challenge.type.enum, no spaces

bharosa.uio.default.challenge.type.enum.MyChallenge.description = Email Challenge // descriptive name

bharosa.uio.default.challenge.type.enum.MyChallenge.processor = oracle.oaam.challenge.processor.challenge.EmailChallengeProcessor  // Processor used for sending emails instance of com.bharosa.uio.processor.challenge.ChallengeProcessorIntf

bharosa.uio.default.challenge.type.enum.MyChallenge.requiredInfo = email  // comma separated field names, User registration flow captures these data fields, check Contact information Inputs section to define this enum

bharosa.uio.default.challenge.type.enum.MyChallenge.available = false // to turn off this service

bharosa.uio.default.challenge.type.enum.MyChallenge.otp = true // indicates this challenge is used for OTP, set it to true

Email Example

bharosa.uio.default.challenge.type.enum.ChallengeEmail = 1
bharosa.uio.default.challenge.type.enum.ChallengeEmail.name = Email Challenge
bharosa.uio.default.challenge.type.enum.ChallengeEmail.description = Email Challenge
bharosa.uio.default.challenge.type.enum.ChallengeEmail.processor =
com.bharosa.uio.processor.challenge.EmailChallengeProcessor
bharosa.uio.default.challenge.type.enum.ChallengeEmail.requiredInfo = mobile
bharosa.uio.default.challenge.type.enum.ChallengeEmail.available = true
bharosa.uio.default.challenge.type.enum.ChallengeEmail.enabled = true

SMS Example

bharosa.uio.default.challenge.type.enum.ChallengeSMS = 2
bharosa.uio.default.challenge.type.enum.ChallengeSMS.name = SMS Challenge
bharosa.uio.default.challenge.type.enum.ChallengeSMS.description = SMS Challenge
bharosa.uio.default.challenge.type.enum.ChallengeSMS.processor =
com.bharosa.uio.processor.challenge.SmsChallengeProcessor
bharosa.uio.default.challenge.type.enum.ChallengeSMS.requiredInfo = mobile
bharosa.uio.default.challenge.type.enum.ChallengeSMS.available = true
bharosa.uio.default.challenge.type.enum.ChallengeSMS.enabled = true

9.3 Configuring the Challenge Pad Used for Challenge

By default, challenge devices are configured through rules. The rules are under the AuthentiPad checkpoint and determine the type of device to use based on the purpose of the device (ChallengeEmail, ChallengeSMS, ChallengeQuestion, and so on).

To create/update policies to use the challenge type:

  1. Add a new rule action, MyChallenge, with the enum, rule.action.enum.

  2. Create policy to return newly created action, MyChallenge, to use the challenge method.

Alternatively, if you want to configure challenge devices using properties, you can bypass the AuthentiPad checkpoint by setting bharosa.uio.default.use.authentipad.checkpoint to false.

Devices to use for the challenge type can be added.

bharosa.uio.<application>.<challengeType>.authenticator.device=<value>

The examples shown use the challenge type key, ChallengeEmail and ChallengeSMS to construct the property name.

bharosa.uio.default.ChallengeSMS.authenticator.device=DevicePinPad
bharosa.uio.default.ChallengeEmail.authenticator.device=DevicePinPad

Available challenge device values are DeviceKeyPadFull, DeviceKeyPadAlpha, DeviceTextPad, DeviceQuestionPad, DevicePinPad, and DeviceHTMLControl.

For instructions on customizing, extending, or overriding Oracle Adaptive Access Manager properties, refer to Chapter 12, "Customizing Oracle Adaptive Access Manager."

9.4 Configuring User Information Properties

Instructions to configure user information properties are in the following sections:

For instructions on customizing, extending, or overriding Oracle Adaptive Access Manager properties, refer to Chapter 12, "Customizing Oracle Adaptive Access Manager."

9.4.1 Configuration Settings for Information Registration and Preferences and PIN Generation

Default configurations for settings for registration of information, preference, and PIN generation are listed as follows:

Contact information registration

bharosa.uio.default.register.userinfo.enabled=false

Contact information preferences

bharosa.uio.default.userpreferences.userinfo.enabled=false

OTP PIN Generation

# Length of the Pin
bharosa.uio.otp.generate.code.length = 5
# Characters to use when generating the Pin
bharosa.uio.otp.generate.code.characters = 1234567890

The AbstractOTPChallengeProcessor class has a default pin generation method, generateCode, that you can override to provide your pin generation logic.

9.4.2 Set Contact Information Inputs

Contact information inputs are defined in userinfo.inputs.enum. The enum element is:

bharosa.uio.<application>.userinfo.inputs.enum.<inputname>

Example

bharosa.uio.default.userinfo.inputs.enum.email=1
bharosa.uio.default.userinfo.inputs.enum.email.name=Email Address
bharosa.uio.default.userinfo.inputs.enum.email.description=Email Address
bharosa.uio.default.userinfo.inputs.enum.email.inputname=email
bharosa.uio.default.userinfo.inputs.enum.email.inputtype=text
bharosa.uio.default.userinfo.inputs.enum.email.maxlength=40
bharosa.uio.default.userinfo.inputs.enum.email.required=true
bharosa.uio.default.userinfo.inputs.enum.email.order=2
bharosa.uio.default.userinfo.inputs.enum.email.enabled=true
bharosa.uio.default.userinfo.inputs.enum.email.regex=.+@[a-zA-Z_]+?\\.[a-zA-Z]{2,3}
bharosa.uio.default.userinfo.inputs.enum.email.errorCode=otp.invalid.email
bharosa.uio.default.userinfo.inputs.enum.email.managerClass=com.bharosa.uio.manager.user.DefaultContactInfoManager

9.4.3 SMS Configuration to Receive OTP via SMS

For OTP to be receive via SMS, you must:

9.4.3.1 Enable Registration and Preference Setting

To enable OTP profile registration and preference setting, set the following properties to true:

  • bharosa.uio.default.register.userinfo.enabled

    Setting the property to true enables the profile registration pages if the OTP channel is enabled and requires registration.

  • bharosa.uio.default.userpreferences.userinfo.enabled

    Setting the property to true enables the user to set preferences if the OTP channel is enabled and allows preference setting.

9.4.3.2 Set Input Information

If user information registration or user preferences is true, configure input information via enum:

bharosa.uio.default.userinfo.inputs.enum

Table 9-2 OTP Properties for Contact Input

Property Description

inputname

Name used for the input field in the HTML form

inputtype

Set for text or password input

maxlength

Maximum length of user input

required

Set if the field is required on the registration page

order

The order displayed in the user interface

regex

Regular expression used to validate user input for this field

errorCode

Error code used to look up validation error message (bharosa.uio.<application ID>.error.<errorCode>)

managerClass

java class that implements com.bharosa.uio.manager.user.UserDataManagerIntf (if data is to be stored in Oracle Adaptive Access Manager database this property should be set to com.bharosa.uio.manager.user.DefaultContactInfoManager)


The following is an example of an enum defining cell phone registration on the OTP registration page of a virtual authentication device:

bharosa.uio.default.userinfo.inputs.enum.mobile=0
bharosa.uio.default.userinfo.inputs.enum.mobile.name=Mobile Phone
bharosa.uio.default.userinfo.inputs.enum.mobile.description=Mobile Phone
bharosa.uio.default.userinfo.inputs.enum.mobile.inputname=cellnumber
bharosa.uio.default.userinfo.inputs.enum.mobile.inputtype=text
bharosa.uio.default.userinfo.inputs.enum.mobile.maxlength=15
bharosa.uio.default.userinfo.inputs.enum.mobile.required=true
bharosa.uio.default.userinfo.inputs.enum.mobile.order=1
bharosa.uio.default.userinfo.inputs.enum.mobile.enabled=true