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
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;
}