Learn F5 Technologies, Get Answers & Share Community Solutions Join DevCentral

Filter by:
  • Solution
  • Technology
code share

Send an One Time Password (OTP) via the Twilio SMS gateway

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:

Image Text

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
    }
}
Tested on Version:
13.0
Comments on this Snippet
Comment made 09-Mar-2018 by Manuel Cristobal 72

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

0
Comment made 10-Mar-2018 by Niels van Sluis 2591

Hi Manuel,

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

Kind regards,

Niels

0
Comment made 3 months ago by AdamM07 0

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?

0
Comment made 3 months ago by Niels van Sluis 2591

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.

0
Comment made 3 weeks ago by kinjeyan 10

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

0
Comment made 3 weeks ago by Niels van Sluis 2591

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?

0
Comment made 3 weeks ago by kinjeyan 10

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

0
Comment made 3 weeks ago by Niels van Sluis 2591

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();
0
Comment made 3 weeks ago by kinjeyan 10

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

0
Comment made 3 weeks ago by Niels van Sluis 2591

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?

0
Comment made 3 weeks ago by kinjeyan 10

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

0
Comment made 3 weeks ago by Niels van Sluis 2591

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

0
Comment made 3 weeks ago by kinjeyan 10
// 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.

0