ISAM create a new OTP Mechanism

I wanted to make a new OTP Mechanism that was called by a JavaScript REST call – that wasn’t the SMS mechanism in the box.

In this example – I tested it with Boxcar – an iOS App that lets you send Push notifications with a simple REST call.

To add a custom mechanism to the ISAM OTP framework, you just need to edit two OTP Mapping rule files:

1) The OTPGetMethods Mapping rule add the new custom rest mechanism – you should see where it has the list:

    //This is an attribute that will show on the template page by default. 
    //I also use it in the OTPDeliver mapping rule to determine if this mechanism
    //Was chosen...
    var destAttribute = "RESTto://somedestination";
    methods.push({
        id                : "genericrest",
        otpType           : "mac_otp",
        deliveryType      : "no_delivery",
        deliveryAttribute :  destAttribute,
        userInfoType      :  "",
        label             : "Custom Rest Callout"
    });

This adds this selection in the UI, which will use the mac_otp mechanism to generate the OTP, but it won’t deliver it using any of the standard mechanisms, since we have declared it to “no_delivery”.

2) Then we look for this to come through the OTPDeliver Mapping rule, and just use the Javascript REST client to call something:

a) Add some imports to the top of the mapping rule,
b) In the mac_otp type, see if they are delivering it to our specified attribute starting with RESTto://
[My additions are in marked with //PHIL and //ENDPHIL]

// OTPDeliver mapping rule.
importClass(Packages.com.tivoli.am.fim.trustserver.sts.uuser.Attribute);

//PHIL
importClass(Packages.com.tivoli.am.fim.trustserver.sts.utilities.IDMappingExtUtils);
importClass(Packages.com.ibm.security.access.httpclient.HttpClient);
importClass(Packages.com.ibm.security.access.httpclient.HttpResponse);
importClass(Packages.com.ibm.security.access.httpclient.Parameters);
//EndPHIL

// Get the STS Universal User context attributes.

var stsuuCtxAttrs = stsuu.getContextAttributesAttributeContainer();

// Get the OTP type selected by the user.

var otpType = stsuuCtxAttrs.getAttributeValueByNameAndType("otp.sts.otp-method.otp-type", "otp.sts.type");

// If the OTP type is mac_otp, then generate the OTP hint and the formatted OTP. Other OTP types, such as hotp_otp, hotp_otp,
// and rsa_otp, do not deliver the OTP to the user.

if (otpType.equals("mac_otp")) {
    // Get the OTP generated by the OTP Provider plug-in.

    var otp = stsuuCtxAttrs.getAttributeValueByNameAndType("otp.sts.otp", "otp.sts.type");

    // Generate the OTP hint. OTP hint is data used to inform the user the OTP that the user must submit. OTP hint is sent to
    // the user together with the OTP as formatted OTP. OTP hint is displayed in OTP Login page.

    var otpHint = Math.floor(1000 + (Math.random() * 9000));

    // Generate the formatted OTP. Formatted OTP is sent to the user.

    var otpFormatted = otpHint + "-" + otp;

    // Set the OTP hint into STS Universal User context attributes.

    var ctxOTPHint = new Attribute("otp.sts.otp-hint", "otp.sts.type", otpHint);
    stsuuCtxAttrs.setAttribute(ctxOTPHint);

    // Set the formatted OTP into STS Universal User context attributes.

    var ctxOTPFormatted = new Attribute("otp.sts.otp-formatted", "otp.sts.type", otpFormatted);
    stsuuCtxAttrs.setAttribute(ctxOTPFormatted);

    //PHIL
    var otpDeliveryAttr = stsuuCtxAttrs.getAttributeValueByNameAndType("otp.sts.otp-method.delivery-attribute", "otp.sts.type");
    IDMappingExtUtils.traceString("##### otpDeliveryAttr: " + otpDeliveryAttr);
    //This is where we check to see if the mech was the custom one.
    if (otpDeliveryAttr != null && otpDeliveryAttr != "" && otpDeliveryAttr.startsWith("RESTto://")) {
        //This is the custom REST OTP Mech.
        // Get the OTP generated by the OTP Provider plug-in.
        // The variable otpFormatted contains the otp formatted for sending. 

        //Use a Javascript REST call here to send otp to some place better...

        IDMappingExtUtils.traceString("OTP is: " + otpFormatted);

        var hr = new HttpResponse();
        var param = new Parameters();
        //POST Param builder using example from OAuth Pre-Token Mapping rule
        param.addParameter("user_credentials", "CUSTOMBOXCARTOKENHERE");
        param.addParameter("notification[title]", "OTP Delivery: " + otpFormatted);
        param.addParameter("notification[sound]", "bird-1");
        param.addParameter("notification[source_name]", "ISAM Server");


        // SSL httpPost - be sure to add certificate to rt trust store
        // This assumes default trust store (util.httpClient.defaultTrustStore in Advanced Configuration panel)
        hr = HttpClient.httpPost("https://new.boxcar.io/api/notifications", param);
        if (hr != null) {
            IDMappingExtUtils.traceString("code: " + hr.getCode());
            IDMappingExtUtils.traceString("body: " + hr.getBody());
        }
        if (hr != null && hr.getCode() == 201) {
            IDMappingExtUtils.traceString("###OTP Sent...");

        } else {
            IDMappingExtUtils.traceString("#### Error Sending OTP");
        }
    }
    //EndPHIL

}

Running the test again, with the custom mechanism, we can see the OTP  hint shown, and the trace strings show the request as succeeding.

Enter OTP

On my phone the notification has arrived:

 

Boxcar Notification

So in order to do a wide variety of mechanisms, either add a new one for each of the desired mechs, or use a proxy that has a different attribute in the rest callout.

In terms of delivery attributes, you have access to the entire users credential at every stage of the process, this means, if you’ve put the attribute in the cred, we can use it as a delivery attribute. These can be accessed at any time with something like:

var mobileNumber = stsuuAttrs.getAttributeValueByName("AttributeNameHere");

Which you see is done already when setting up the methods in OTPGetMethods mapping rule.

In 9.0.2.1 we can also query LDAP using the javascript “UserHelper” class –
Here is an example snippet where I might get the mail attribute from a user “someusername”.

importClass(Packages.com.ibm.security.access.user.UserLookupHelper);
importClass(Packages.com.ibm.security.access.user.User);

var hlpr1 = new UserLookupHelper();
//Use the server credentials as detailed in the Username/Password Mechanism Config
hlpr1.init(true);

user1 = hlpr1.getUser("someusername");
var mail = user1.getAttribute("mail");

We could also use the REST command above to make a callout to enrich the data from another source.

 

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

WordPress.com.

Up ↑

%d bloggers like this: