Develop a Script for Risk-Based Authentication

This tutorial helps you develop a script for controlling risk-based authentication and out-of-band methods such as SMS and email.

Prerequisites

  • You have configured your policy configuration (application) to use the TOTPLoginModule with otp&pwd mode. For more information, see Configuring TOTPLoginModule and RBALoginModule.

  • You have user and administrator permissions.

  • You have configured the application to send passcodes via SMS. For more information, see Configuring Authentication with a Random Passcode Sent by SMS, E-Mail, or Another Channel.

  • You have configured the user e-mail in the user management engine (UME). For more information, see Identity Management.

  • You have created a mail policy script of type Library in the Policy Script Administration Console at http(s)://<host>:<port>/ssoadmin/scripts with the following content:

    var EMAIL = {
      send : function (recipient, subject, body, logger) {
        try {
          var server = com.sap.security.api.UMFactory.getProperties().getDynamic("ume.notification.mail_host", "mail");
          var sender = com.sap.security.api.UMFactory.getProperties().getDynamic("ume.notification.system_email", "no-reply@promptep.com");
          
          // Define the properties for the email and its gateway
          var properties = new java.util.Properties();
          properties.put("mail.smtp.host", server);
          // [uncomment to troubleshoot SMTP issues] properties.put("mail.debug", true);
          
          var session = javax.mail.Session.getInstance(properties);
          // [uncomment to troubleshoot SMTP issues] session.setDebug(true);
          // [uncomment to troubleshoot SMTP issues] session.setDebugOut(java.lang.System.err);
          
          var msg = new javax.mail.internet.MimeMessage(session);
          
          // Sender
          var addressFrom = new javax.mail.internet.InternetAddress(sender);
          msg.setFrom(addressFrom);
          
          // Recipient 
          var addressTo = java.lang.reflect.Array.newInstance(javax.mail.internet.InternetAddress, 1);
          addressTo[0] = new javax.mail.internet.InternetAddress(recipient);
          msg.setRecipients(javax.mail.Message.RecipientType.TO, addressTo[0]);
          
          // Set the header of the email
          msg.setSubject(subject, "utf-8");
          
          // Set the content of the email
          msg.setContent(body, "text/plain; charset=utf-8");
          
          // [uncomment to troubleshoot SMTP issues] msg.writeTo(java.lang.System.err);
          
          // Send email
          javax.mail.Transport.send(msg);
          
          return true;
        } catch(err) {
          logger.traceError("Passcode cannot be sent via email.", err);
          return false;
        }
      }
    }
    

    For more information, see Working with Policy Scripts.

Procedure

  1. Log on to the Policy Script Administration Console at http(s)://<host>:<port>/ssoadmin/scripts.
  2. Create a new policy script with one of the scripts below and save your configurations. If you have created more than one version of your policy script, make sure that the version you want to be executed is activated. For more information on how to create a policy script, see Working with Policy Scripts.
    Recommendation

    To get a better grasp of the scenarios, you should try out the various scripts sequentially.

  3. Log on to the One-Time Password Administration UI at http(s)://<host>:<port>/ssoadmin/otp.
  4. Choose the Settings tab.
    Note

    To allow applications to use your policy script, make sure that the Policy checkbox under the Two-Factor Authentication section is selected.

  5. Choose the Policy Script... button under the Two-Factor Authentication section.
  6. From the dropdown list select the policy script that you have just created, and reload it. Only the activated versions of policy scripts are visible in the dropdown list.
  7. Save your configuration.
  8. Test the scenario as a user.

Script 1: Control First Factor Logon

The following script sets conditions for authentication with Kerberos tokens or with a password.

function onInitialize(config, context) {
  if (context.getHttpClientContext().getClientIP() == "10.11.12.13") {
    config.setProperty("tfa.first.factor.login.module", "SPNegoLoginModule");
  } else {
    config.setProperty("tfa.first.factor.login.module", "BasicPasswordLoginModule");
  }
}

Script 2: Set a Condition for Second Factor Logon

The following script controls the first factor logon and also requires a second factor for authentication when the user is a member of the Managers group.

function onInitialize(config, context) {
  if (context.getHttpClientContext().getClientIP() == "10.11.12.13") {
    config.setProperty("tfa.first.factor.login.module", "SPNegoLoginModule");
  } else {
    config.setProperty("tfa.first.factor.login.module", "BasicPasswordLoginModule");
  }
}

function onFirstStageLogin(config, context, result) {
  var user = context.getLoginInfo().getUser();
  if (!user.isMemberOfGroup('GRUP.PRIVATE_DATASOURCE.un:Managers', true)) {
    result.doNotRequireSecondFactor();
  }
}

Script 3: Set Conditions for Out-of-Band Methods

This script accomplishes the following:

  • Controls the first factor logon in accordance with a specific IP.

  • Defines the second factor logon in accordance with the user role.

  • Creates and sends a passcode via SMS if the user's OTP account is disabled.

  • Creates and sends a passcode by e-mail if a mobile number is not specified in the user management engine.

    The script also defines the e-mail text and the message shown on the logon screen.

  • Shows an error message and aborts the logon if the application cannot send a passcode.

#include "mail";

function onInitialize(config, context) {
  if (context.getHttpClientContext().getClientIP() == "10.11.12.13") {
    config.setProperty("tfa.first.factor.login.module", "SPNegoLoginModule");
  } else {
    config.setProperty("tfa.first.factor.login.module", "BasicPasswordLoginModule");
  }
}

function onFirstStageLogin(config, context, result) {
  var logger = context.getLogger();
  var loginInfo = context.getLoginInfo();
  var user = loginInfo.getUser();
  if (!user.isMemberOfGroup('GRUP.PRIVATE_DATASOURCE.un:Managers', true)) {
    result.doNotRequireSecondFactor();
  }
  var totpInfo = loginInfo.getTOTPInfo();
  if (totpInfo.getStatus() == totpInfo.DISABLED || totpInfo.getStatus() == totpInfo.EXPIRED) {
    if (user.getCellPhone()) {
      config.setProperty("tfa.passcode.via.sms", "yes");
      var passcode = result.setRandomPasscode(10, 15, 5, "Passcode sent via SMS. Please enter the passcode to log on.");
    } else if (user.getEmail()) {
      config.setProperty("tfa.passcode.via.sms", "no");
      var passcode = result.setRandomPasscode(10, 15, 5, "Passcode sent via email. Please enter the passcode to log on.");
      EMAIL.send(user.getEmail(), "Access to CompanyA Inc. Portal", "Hello " + user.getFirstName() + " " + user.getLastName() + ",\n\nTo log on, please enter the following passcode: " + passcode + ".\n\nYour Portal IT Team", logger);
    } else {
      result.abortLogin('Passcode cannot be sent via SMS or email. Please contact system administrator.');
    }
  }
}

Script 4: Set Time Constraints

This script accomplishes the following:

  • Controls the first factor logon.

  • Allows users to log on during working hours.

    The script defines working hours as Mon - Fri, from 9:00 to 18:00.

  • Defines the second factor logon in accordance with the user role.

  • Creates and sends a passcode via SMS or e-mail if a user does not have a supported device.

    The script also defines the e-mail text and the message shown on the logon screen.

  • Shows an error message and aborts the logon if the application cannot send a passcode.

#include "mail";

function onInitialize(config, context) {
  if (context.getHttpClientContext().getClientIP() == "10.55.83.89") {
    config.setProperty("tfa.first.factor.login.module", "SPNegoLoginModule");
  } else {
    config.setProperty("tfa.first.factor.login.module", "BasicPasswordLoginModule");
  }
}

function onFirstStageLogin(config, context, result) {
  var logger = context.getLogger();
  var loginInfo = context.getLoginInfo();
  var user = loginInfo.getUser();
  if (!isInWorkingHours(logger)) {
     result.abortLogin('You are not allowed to log on outside of working hours.');
	return;
  }
  if (!user.isMemberOfGroup('GRUP.PRIVATE_DATASOURCE.un:Managers', true)) {
    result.doNotRequireSecondFactor();
  }
  var totpInfo = loginInfo.getTOTPInfo();
  if (totpInfo.getStatus() == totpInfo.DISABLED || totpInfo.getStatus() == totpInfo.EXPIRED) {
    if (user.getCellPhone()) {
      config.setProperty("tfa.passcode.via.sms", "yes");
      var passcode = result.setRandomPasscode(10, 15, 5, "Passcode sent via SMS. Please enter the passcode to log on.");
    } else if (user.getEmail()) {
      config.setProperty("tfa.passcode.via.sms", "no");
      var passcode = result.setRandomPasscode(10, 15, 5, "Passcode sent via email. Please enter the passcode to log on.");
      EMAIL.send(user.getEmail(), "Access to CompanyA Inc. Portal", "Hello " + user.getFirstName() + " " + user.getLastName() + ",\n\nTo log on, please enter the following passcode: " + passcode + ".\n\nYour Portal IT Team", logger);
    } else {
      result.abortLogin('Passcode cannot be sent via SMS or email. Please contact system administrator.');
    }
  }
}

function isInWorkingHours(logger) {
  var now = new Date();
  logger.traceDebug("Login time " + now);
  return now.getDay() >= 1 && now.getDay() <= 5 && now.getHours() >= 9 && now.getHours() < 18;
}