Cross-Platform Cloud-based Anonymous Messaging with Flowroute

Posted on December 8, 2016

The combination of the Internet, cloud and mobile access has created unprecedented access between buyers and sellers of services. Companies like Netflix (movies), Uber (Taxis), and Airbnb (hotels) have completely displaced traditional brick-and-mortar organizations and created immediate access to goods and services through handheld devices. The increase of transactions conducted on smartphones comes at a cost, however. The greater exposure of personally identifiable information results in greater security risk and vulnerability. Your mobile phone is an example of a device that can be uniquely linked to your identity through your cell phone number.

Service providers concerned with the privacy of their users must offer solutions that enable quality customer service without compromising security. One way to accomplish this is through anonymous communication. This enables the consumer to interact with the service provider via a channel that protects their personally identifiable information. As an example, you may want to be able to text a vendor you “met” online with questions but don’t want to compromise your personal information. The anonymous communications solution for this is called “masked numbers” and allows you to use a proxy or intermediary number to facilitate conversations.

This article explores a cross-platform solution leveraging Microsoft’s .NET Core (a version of the popular .NET Framework that can run on Linux, Windows, or MacOS platforms), the Flowroute® v2 API, and Azure App Services. To get started, you’ll need a few prerequisites:

– Either Visual Studio 2015 or the cross-platform Visual Studio Code to develop your application (visualstuidio.com) (note: the examples in the article follow Visual Studio 2015, although the application can be built with Visual Studio Code the deployment to Azure is different)

– A Flowroute account: https://www.flowroute.com/

– A number either provisioned through or registered with Flowroute: https://manage.flowroute.com/accounts/dids/

– Your Access Key and Secret Key: https://manage.flowroute.com/accounts/preferences/api/

– An SMS Callback configured (you must click the “Enable SMS” button to enable inbound text messages, this will be covered later)

– An Azure account (you can sign up for a free credit if you don’t already have an account): https://azure.microsoft.com/en-us/

– The Azure SDK for Visual Studio 2015: https://azure.microsoft.com/en-us/downloads/

To install the .NET Core on your system, follow the instructions at:

https://www.microsoft.com/net/core

These instructions assume you are using Visual Studio 2015. If you are using Visual Studio Code, you can download the associated source code to follow along (the project will run using either IDE). This article explains how to push to Azure App Service using Visual Studio Code: https://azure.microsoft.com/en-us/blog/visual-studio-code-and-azure-app-service-a-perfect-fit/.

The project will leverage the Flowroute V2 API and a Flowroute number to broker text messages between two different numbers. Figure 1 illustrates the general concept. A user initiates a conversation with a keyword “start” to the masked number. The Flowroute API triggers a callback to a REST service endpoint you specify, and posts that code with the person they wish to text – for example, this may be displayed on a website, sent over email, or displayed in a mobile app. The recipient user texts the same masked number a join request, then the two carry on conversations as if they are texting directly. Each person only sees the masked number. A special text command ends the discussion.

Code 5

Figure 1: Anonymous Communication Flow

 

To get started, create a new ASP.NET Core Web Application project as shown in Figure 2. This will create a boilerplate for the application, including an example controller and end point so that you can test the application.

Code 4

Figure 2: New Project

 

A second dialog (Figure 3) allows you to choose an empty project, Web API, or Web Application. Choose the Web API project. If you are already familiar with Azure and have an app service set up, you can check the option to host in the cloud. Otherwise, leave this unchecked. Configuring the Azure service and deploying the web app will be covered later. Once the project is created you can hit F5 to debug and confirm it runs correctly.

The next step is to create a test project. From the command line or shell, navigate to the root directory of your application. This should contain the solution file for your project. The example code named the solution FlowrouteVirtMsg so the root directory contains the file FlowrouteVirtMsg.sln and a subdirectory named src. Type the command:

dotnet new -t xunittest

Code 3

Figure 3: Web API

 

This will scaffold a test project. From Visual Studio, you can right-click on the solution and choose “add existing project” then navigate to test/project.json or test/test.xproj to add the project to the solution. From the test project, right-click and add a reference to the FlowrouteVirtMsg project so that you are able to author tests based on components defined in the web project. You should see a project structure similar to what is shown in Figure 4.

code 2

Figure 4: Project Structure

 

In order to send text messages, the project will use the Flowroute .NET SDK located at:

https://github.com/flowroute/flowroute-net-sdk

To install the package, open the NuGet Package Manager console and type the command:

install-package Flowroute

This will pull down the required libraries and reference them in your project as shown in Figure 5.

code_am_1

Figure 5: NuGet

 

The example project implements the workflow with two business objects. The first, named Conversations, keeps track of discussions. A discussion is represented by the Conversation class:

Messaging Image 9

This class keeps track of the two numbers, the code, and exposes a flag to indicate whether the conversation has started.

Note: to keep the example simple, the implementation for this demo uses a singleton, in-memory dictionary to manage conversations. This prevents the solution from being load-balanced and will lose information if the server is restarted. A more robust, production-ready implementation would use a repository for the information, for example, a SQL database or Redis.

The business logic is modeled with a set of tests contained in the ConversationTests class. The following set of tests specify how conversations are started:

Messaging Image 8

Note that the tests follow a pattern known as “design-by-contract” and expect the API to throw specific errors when invalid data is passed. Also, note this class does not interact with any external APIs such as the messaging API. Instead, its Single Responsibility is to manage conversations – starting, joining, brokering, and ending as needed.

Here is the implementation of the Start method (note it uses thread constructs to synchronize access to the dictionary – although a concurrent dictionary would work as well, the locks won’t be necessary when using a persistent database or backing store).

Messaging Image 6

The algorithm checks the incoming parameters, ensures the phone number is not already involved in a different conversation, then generates a unique code and returns it to the caller.

Note: for the purpose of this example, it is assumed duplicate random numbers will not be generated. For production, the code should be improved to first check to ensure a code is not in use before returning it, and generate a new one if needed.

Refer to the reference project for the remaining tests and implementation.

A second business object facilitates the parsing of text messages. It takes the phone number that initiated the text and the body of the text and determines whether the text is issuing a command to start, join, or end a conversation, or is simply part of an ongoing discussion. The ParseResult class encapsulates the command and related information:

Command type 2

The command types map to the flow that was diagrammed earlier:

Command type 1

A set of tests in ParserTests specify the expected behavior. Here are a few of the unit tests:

screen-shot-2016-12-07-at-9-41-05-am

After the business logic has been programmed, it is wired into the controller. In the web API project, rename the ValuesController to MessageController. The Flowroute documentation specifies how to set up the callback URL and what the messages look like: http://developer.flowroute.com/docs/receive-an-inbound-message. The InboundMessage class encapsulates the data that will be passed from Flowroute:

Messaging Image 2

The controller sets up values for the access keys and the Flowroute number to be used as the masked number.

Note: for production applications, you would not hardcode the key and secrets in the code. Instead, you can use environment variables and configure them in production, or leverage a solution like Azure Key Vault: https://azure.microsoft.com/en-us/services/key-vault/. You might also consider managing an array of available numbers; this example uses just one single masked number.

The constructor for the controller takes in an instance of Conversations because it must be configured as a singleton to work across multiple requests. The singleton is configured in Startup.cs:

Messaging Image 1

The main logic of the controller is concerned with parsing the text, then passing the right commands to manage the conversation. If an error is thrown, it returns a bad request, otherwise, it returns success. Keep in mind this endpoint is being called from Flowroute as the result of an incoming text message.

Note: to secure this service and prevent malicious attacks, you should implement security so that requests are only allowed from Flowroute’s servers and valid numbers you manage in Flowroute. Furthermore, production apps should leverage SSL for communications (this example uses plain HTTP for simplicity).

Here is the main logic:

Code 2

And here is the example method call to pass-through a message (using the “talk” command):

Code 1

A few notes for this implementation. First, for testing purposes, you might want to abstract the messaging API behind an interface. In production, that interface will be implemented with a call to the messaging service. In the test, it can simply write to the console or use another mechanism to avoid actual text-based charges on your account. Second, the message call returns a result that indicates whether an error is encountered. The example code does not parse that error, but a production implementation should parse it and log it out and return an exception if the call does not succeed.

Once the codebase is fully implemented, you are ready to publish your end point. From the Azure Portal at https://portal.azure.com/ you can tap “App Services”, click the “Add” button and select “Web App”. Click the Create button as shown in Figure 6.

Web App Image

Figure 6: App Services

 

Give the application a name and a resource group as shown in Figure 7. In this example, the URL will be http://FlowrouteMesaging.azurewebsites.net/ (this is not an active endpoint but just an example for the article).

Figure 7

Figure 7: Resource Group

 

After the app service is up and running, you are ready to publish. From Visual Studio, select “Build” then “Publish FlowrouteVirtMsg.” Choose “Microsoft Azure App Service” as the target. Select your subscription and resource group and then select the app service. Figure 8 illustrates my selection of the FlowrouteMessaging app service.

Figure 8

Figure 8: Deployment

 

The next dialog will automatically pull in all of the credentials needed to publish. You can click the Validate Connection button to ensure everything is wired in correctly. Click Publish and your application is ready to broker anonymous conversations! Be sure to visit your Flowroute API Preferences (https://manage.flowroute.com/accounts/preferences/api/) to enter the callback endpoint, then click the Enable SMS button as shown in Figure 9. The callback URL is the URL of the app service followed by /api/message.

Figure 9

Figure 9: Enable Callbacks

 

Now you can engage in a conversation. Text Start to your Flowroute number, and you should receive a code. Share that with another person, and instruct them to text Join <Code> to join the conversation. Figure 10 shows a sample conversation. The other participate texted End <Code> to end the conversation.

Note: text messaging rates apply! You can also test the solution locally by manually posting messages to the API end point to simulate a conversation using a tool like PostMan.

Figure 10

Figure 10: Text Messages

 

The solution presented here is a small demo of what’s possible leveraging the combination of cloud services, modern cross-platform web development, and the Flowroute API. This project illustrates management of both inbound and outbound text messages leveraging the Flowroute .NET SDK. There are many more functions you can perform, out of the box examples and in-depth API documentation available at the Flowroute Developer Portal: https://developer.flowroute.com/. You can sign up for an account and integrate advanced messaging services in your own applications within minutes!