20 Developing Custom Challenge Processors

The OAAM Server provides a challenge processor framework that allows for custom implementations of challenge mechanisms.

This chapter contains the following sections:

20.1 What are Challenge Processors

A challenge processor is java code that implements the ChallengeProcessorIntf interface or extends the AbstractChallengeProcessor class.

Challenge processors can be created to perform the following tasks for a challenge:

  • Generate challenge secret (password) to send to the user.

  • Validate the user answer

  • Control delivery wait page (if needed)

  • Check if delivery service is available (if needed)

For example, 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 by a challenge type.

20.2 Code Challenge Processors

This section contains information on the challenge processor class and methods to implement. An implementation example is also provided for your reference.

20.2.1 Class

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.

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

20.2.2 Methods

The methods used in a challenge processor are listed in the sections following.

Table 20-1 Challenge Processor Methods

Methods Description

protected boolean generateSecret(UIOSessionData sessionData, boolean isRetry)

This method is used to generate code to send to client

protected boolean validateAnswer(UIOSessionData sessionData, String answer)

This method is used to validate the user answer.

public String checkDeliveryStatus(UIOSessionData sessionData, boolean userWaiting, boolean isRetry)

This method is used if you want to provide a wait until message is sent.

public boolean isServiceAvailable(UIOSessionData sessionData)

This method is used to check if external service is available.


20.2.3 Example: Email Challenge Processor Implementation

An implementation of the email 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;
  }
}

20.2.4 Secret (PIN) Implementation

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

20.3 Define the Delivery Channel Types for the Challenge Processors

This section contains instructions on defining a delivery channel type. Examples are provided for your reference.

20.3.1 Challenge Type Enum

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>

For example,

bharosa.uio.default.challenge.type.enum.ChallengeEmail

The challenge type enum is used to associate a challenge type with the java code needed to perform any work related to that challenge type. An example of implementing an email challenge processor is shown in Section 20.2.3, "Example: Email Challenge Processor Implementation."

The Challenge Type ID (for example, ChallengeEmail) should match a rule action returned by the rules when that challenge type is used. The rule action for ChallengeEmail is rule.action.enum.ChallengeEmail. The rule action is to challenge the user using email using the email delivery channel. "Channel" normally refers to the delivery channel used to send to the user.

20.3.2 Example: Defining an OTP Channel Type

To define a challenge type, use the following property:

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

In the property, default is the UIO application name, and MyChallenge is the Challenge Type being added. For example, ChallengeEmail is the Challenge Type in the example below.

bharosa.uio.default.challenge.type.enum.ChallengeEmail

The rule action is to challenge the user with email using the email delivery channel.

rule.action.enum.ChallengeEmail

To enable/disable a challenge type, the available flag should be set:

bharosa.uio.default.challenge.type.enum.MyChallenge.available = false 

Table 20-2 Challenge type Flags

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


Setting the available flag and setting the enabled flag are different. The enabled flag would remove it from list.

Example for Defining a Channel Type

Attributes bharosa.uio.default.challenge.type.enum with example values are 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

20.4 Configure User Input 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 7, "Customizing Oracle Adaptive Access Manager."

20.4.1 Enable Registration and Preferences Input

Default configurations for enabling for registration and preference input are listed as follows:

Contact information registration

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

Contact information preferences

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

20.4.2 Set Contact Information Inputs

If user information registration and user preferences are true, configure input information.

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

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

Table 20-3 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)


Email Input 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

20.5 Configure the Challenge Pads Used for Challenge Types

By default, challenge devices that will be used are configured through rules. The rules are under the AuthentiPad checkpoint where you can specify the type of device to use based on the purpose of the device.

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.

Table 20-4 Authentication Device Type

Property Description

None

No HTML page or authentication pad

DeviceKeyPadFull

Challenge user using KeyPad.

DeviceKeyPadAlpha

Challenge user with the alphanumeric KeyPad (numbers and letters only, no special characters)

DeviceTextPad

Challenge user using TextPad.

DeviceQuestionPad

Challenge user using QuestionPad.

DevicePinPad

Challenge user using PinPad.

DeviceHTMLControl

Challenge user using HTML page instead of an authentication pad.