cancel
Showing results for 
Search instead for 
Did you mean: 

Problem this snippet solves:

This snippet makes it possible to send an One Time Password (OTP) via the Twilio SMS gateway. This snippet uses iRuleLX and the node.js twilio package to interact with the Twilio API.

How to use this snippet:

Prepare the BIG-IP

  • Provision the BIG-IP with iRuleLX.
  • Create LX Workspace: workspace_twilio
  • Add iRule: irule_twilio
  • Add Extension: extension_twilio
  • Add LX Plugin: plugin_twilio -> From Workspace: workspace_twilio

Install the node.js twilio module

# cd /var/ilx/workspaces/Common/workspace_twilio/extensions/extension_twilio
# npm install twilio --save
  /var/ilx/workspaces/Common/workspace_twilio/extensions/extension_twilio
  └─┬ twilio@3.13.0 
  (lots and lots of modules follow...)
#

iRule

To make it works, you need to install the irule on the Virtual Server that publish your application with APM authentication.

Access Profile

If you already have an existing access profile, you will need to modify it and include some additional configuration in your VPE. If you have no access profile, you can starts building your own based on the description we provide below.

Configuring the Visual Policy Editor

The printscreen below is a minimal Visual Policy Editor used to make Twilio OTP Authentication works properly:

0151T000003d9DSQAY.PNG

IE – Twilio

This is an Irule Event with the ID set to twilio. This will trigger the irule_twilio iRule to come into action.

EA - Twilio Status

This is an Empty Action with two branches. The branch named "successful" contains the following expression : expr { [mcget {session.custom.twilio.status}] starts_with "SM" }

Message Box

This is a Message Box that will inform the user that there was a failure sending the One Time Password. For example: Oops, something went wrong. Please login again.

irule_twilio

when ACCESS_POLICY_AGENT_EVENT {
    if { [ACCESS::policy agent_id ] eq "twilio" } {

        set username "[ACCESS::session data get session.logon.last.username]"
        set generatedOTP "[ACCESS::session data get session.otp.assigned.val]"
        set telephoneNumber "[ACCESS::session data get session.ad.last.attr.telephoneNumber]"

        # The sender of the message. From a valid Twilio number.
        set sender "+31123456789"

        if {[info exists username] && ($username eq "")} {
            log local0. "Error: username variable is empty; no OTP sent."
            return
        }

        if {[info exists generatedOTP] && ($generatedOTP eq "")} {
            log local0. "Error: generatedOTP variable is empty; no OTP sent for user $username."
            return
        }

        if {([info exists telephoneNumber] && $telephoneNumber eq "")} {
            log local0. "Error: telephoneNumber variable is empty; no OTP sent for user $username."
            return
        }

        set rpc_handle [ ILX::init plugin_twilio extension_twilio]
        if {[ catch { ILX::call $rpc_handle sendOTP $generatedOTP $telephoneNumber $sender } result ] } {
            log local0. "sendOTP failed for telephoneNumber: $telephoneNumber, ILX failure: $result"
            return
        }

        log local0. "Twilio status for user $username ($telephoneNumber): $result"
        ACCESS::session data set session.custom.twilio.status $result
    }
}

Code :

// Import the f5-nodejs module.
var f5 = require('f5-nodejs');
 
// Create a new rpc server for listening to TCL iRule calls.
var ilx = new f5.ILXServer();

const accountSid = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'; // Your Account SID from www.twilio.com/console
const authToken = 'your_auth_token';   // Your Auth Token from www.twilio.com/console

const client = require('twilio')(accountSid, authToken);
 
ilx.addMethod('sendOTP', function(req, res) {
    var generatedOTP = req.params()[0];
    var telephoneNumber = req.params()[1];
    var sender = req.params()[2];
    var message = 'Your OTP is: ' + generatedOTP;
    
    client.messages.create({
        body: message,
        to: telephoneNumber,  // Text this number
        from: sender // From a valid Twilio number
    })
    .then(function(message) {
            return res.reply(message.sid);
    });
    
});
 
// Start listening for ILX::call and ILX::notify events.
ilx.listen();

Tested this on version:

13.0
Comments
Manuel_Cristob2
Nimbostratus
Nimbostratus

One more question... Where do I paste the code (node.js the entire 30 lines)? Do I modify/replace the index.js under this path with the code? PATH--- workspace_twilio=>extension_twilio=>f5-nodesjs=>twilio=>index.js

 

Thanks again

 

Manuel

 

Hi Manuel,

 

You can replace the nodejs javascript in the index.js file with the javascript code in this snippet.

 

Kind regards,

 

Niels

 

AdamM07_249516
Nimbostratus
Nimbostratus

Niels,

 

I keep getting the error "Unable to find app_project (plugin_twilio) when applying the iRule to a VIP.

 

I have the following directory:

 

/var/ilx/workspaces/Common/workspace_twilio/extensions/extension_twilio

 

Under it I have:

 

Any ideas?

 

No idea. I have never seen this error message. Only thing I never done is pulling the package.json. With exception of running the npm install command, I configure everything from the workspace.

 

kinjeyan_365942
Nimbostratus
Nimbostratus

Have you test it with Alphanumeric id instead of number? I can't get it work with.

 

To what ID are you referring to? If you are talking about the accountSid, then I have used an alphanumeric ID. Do you get an error message? What does /var/log/ltm show?

 

kinjeyan_365942
Nimbostratus
Nimbostratus

I mean istead of (set sender "+31123456789") use (set sender "blablabla") on irule or use (messagingServiceSid: 'MG5XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX') instead of (from: sender) on index.js

 

I didn't try that myself, but according to the docs you should use something like this:

 

// Download the helper library from https://www.twilio.com/docs/node/install // Your Account Sid and Auth Token from twilio.com/console const accountSid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'; const authToken = 'your_auth_token'; const client = require('twilio')(accountSid, authToken); client.messages .create({ body: 'Phantom Menace was clearly the best of the prequel trilogy.', messagingServiceSid: 'MG9752274e9e519418a7406176694466fa', to: '+441632960675' }) .then(message => console.log(message.sid)) .done();
kinjeyan_365942
Nimbostratus
Nimbostratus

That's what i tried but doesn't seem to work. i fallback on EA - Twilio Status

 

You should see the output of this log message back in /var/log/ltm:

 

log local0. "Twilio status for user $username ($telephoneNumber): $result"

 

What result do you get?

 

kinjeyan_365942
Nimbostratus
Nimbostratus

I get this error (Rule /Common/irule_twilio : sendOTP failed for telephoneNumber: XXXXXXXXXXXX, ILX failure: ILX timeout. invoked from within "ILX::call $rpc_handle sendOTP $generatedOTP $telephoneNumber $sender ") when i try to send with messagingServiceSid

 

Can you share the whole content of your index.js?

 

kinjeyan_365942
Nimbostratus
Nimbostratus
// Import the f5-nodejs module. var f5 = require('f5-nodejs'); // Create a new rpc server for listening to TCL iRule calls. var ilx = new f5.ILXServer(); const accountSid = 'AC7XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'; // Your Account SID from www.twilio.com/console const authToken = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'; // Your Auth Token from www.twilio.com/console const client = require('twilio')(accountSid, authToken); ilx.addMethod('sendOTP', function(req, res) { var generatedOTP = req.params()[0]; var telephoneNumber = req.params()[1]; var sender = req.params()[2]; var message = 'Your OTP is: ' + generatedOTP; client.messages.create({ body: message, to: telephoneNumber, // Text this number messagingServiceSid: 'MGXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', from: sender // From a valid Twilio number }) .then(function(message) { return res.reply(message.sid); }); }); // Start listening for ILX::call and ILX::notify events. ilx.listen();

If i sent with this, message is sent and i also see Service Name on twilio dashboard, but i receive the sms with number as sender.

 

If i commnet "messagingServiceSid", message still sent but i don't see Service Name on twilio dashboard and this is right.

 

But if i comment "from", message never arrive at twilio.

 

jamie_staples
Nimbostratus
Nimbostratus

Has anyone tried this on newer versions of BIG-IP (14? 15? 16?)

Version history
Last update:
‎09-Mar-2018 09:01
Updated by:
Contributors