Web Based Business Uses Two-Factor Authentication
What is Two Factor Authentication?
Two Factor Authentication, also known as 2FA, two step verification or TFA (as an acronym), is an extra layer of security known as "multi factor authentication" that requires not only a password and username, but also something that the user has on them. Using a username and password together with a piece of information that only the user knows makes it harder for potential intruders to gain access and steal that person's personal data or identity.
How can CallFire help you implement 2FA for your service?
CallFire provides two ways of delivering messages to end-users by voice or by short text message (SMS). Usually two factor authentication is implemented using SMS; however, we will show both variants with voice and SMS. The following examples show how to send a text message with a secret code to a user:
[[code-container]] [+curl] request:
#!/usr/bin/env bash
curl -u username:password -H "Content-Type:application/json" -X POST -d '
[
{
"phoneNumber":"12135551100",
"message":"Your one-time code is 2517",
"attributes":
{
"external_user_id":"45450007002"
}
}
]' "https://api.callfire.com/v2/texts"
response:
{
"items": [
{
"id": 13413,
"fromNumber": "67076",
"toNumber": "12135551100",
"state": "READY",
"campaignId": 20,
"batchId": 14,
"contact": {
"id": 4096,
"homePhone": "12135551100"
},
"attributes": {
"external_user_id":"45450007002"
},
"inbound": false,
"created": 1443403042000,
"modified": 1443403042000,
"message": "Your one-time code is 2517"
}
]
}
[-curl]
[+java]
import com.callfire.api.client.CallfireClient;
import com.callfire.api.client.api.callstexts.model.Text;
import com.callfire.api.client.api.campaigns.model.TextRecipient;
import java.util.Arrays;
import java.util.List;
class ApiClientSample {
public static void main(String[] args) {
CallfireClient client = new CallfireClient("api_login", "api_password");
TextRecipient r1 = new TextRecipient();
r1.setPhoneNumber("12135551100");
r1.setMessage("Your one-time code is 2517");
// Set custom attribute
r1.getAttributes().put("external_user_id", "45450007002");
List<TextRecipient> recipients = Arrays.asList(r1);
List<Text> texts = client.textsApi().send(recipients);
}
}
[-java]
[+csharp]
using System.Collections.Generic;
using CallfireApiClient;
using CallfireApiClient.Api.CallsTexts.Model;
public class ApiClientSample
{
public static void Main(string[] args)
{
var client = new CallfireClient("api_login", "api_password");
var recipient1 = new TextRecipient
{
Message = "Your one-time code is 2517",
PhoneNumber = "12135551100",
// set custom recipient attributes, they are available only to a single Call/Text
// action, do not confuse them with contact fields which are stored with contact
// and are available to each Call/Text where contact is attached to
Attributes = new Dictionary<string, string>
{
{"external_user_id", "45450007002"}
}
};
IList<Text> texts = client.TextsApi.Send(new List<TextRecipient> {recipient1});
}
}
[-csharp]
[+js]
'strict'
const CallfireClient = require('callfire-api-client-js');
const client = new CallfireClient('api-login', 'api-password');
client.ready(() => {
client.texts.sendTexts({
body: [
{
phoneNumber: '12135551100',
message: 'Your one-time code is 2517',
attributes: {
external_user_id: '45450007002'
}
}
]
})
.then((response) => {
console.log(response.obj);
})
.catch((err) => {
console.log('request error ' + err.data);
});
},
(clientError) => {
console.log('client error ' + clientError);
}
);
[-js]
[+python]
from callfire.client import CallfireClient
client = CallfireClient('api-login', 'api-password')
response = client.texts.sendTexts(
body=[
{
'phoneNumber': '12135551100',
'message': 'Your one-time code is 2517',
'attributes': {
'external_user_id': '45450007002'
}
}
]
).result()
# see sample JSON response for this API
# on 'curl' samples tab
print(response)
[-python]
[+php]
<?php
class ApiClientSample {
public static function main() {
$client = \CallFire\Api\DocumentedClient::createClient("login", "password");
$request = $client->sendTexts();
$body = '[
{
"phoneNumber":"12135551100",
"message":"Your one-time code is 2517",
"attributes":
{
"external_user_id":"45450007002"
}
}
]';
$request->getOperationConfig()->setBodyParameter($body);
$result = $client->request($request);
$json = json_decode($result->getBody());
}
}
ApiClientSample::main();
[-php]
[[/code-container]]
See the Send Texts API for detailed information about accepted parameters and responses.
Now, the user can enter a secret code - 2517 - that just came on his phone, and sign in successfully.
Let's see how to send a voice message to a recipient with a secret code. This can be achieved via simple voice call or an IVR call, but with an IVR, you have advanced configuration options (repeating the played message, adding an interactive menu, etc.). The next XML sample represents a CallFire IVR dialplan which does the following:
- detects if the call is answered by a human or an answering machine, then plays a message or hangs up the phone.
- once the message is played, waits for user input before a given timeout (in our case 3500 milliseconds).
- if users presses "1," repeats the voice message, otherwise hangs up the phone.
Ivr<dialplan name="Root">
<!-- answering machine detection -->
<amd>
<!-- if call is answered by human go to live menu -->
<live>
<goto>live</goto>
</live>
<!-- hangup if answering machine detected -->
<machine>
<goto>hangup</goto>
</machine>
</amd>
<menu maxDigits="1" timeout="3500" name="live">
<!-- play text message with secure code -->
<play type="tts" voice="female1" name="play_code">Hello, your one-time code is 2 5 1 7, press 1 to repeat.</play>
<!-- user has pressed 1, repeat starting from menu entry -->
<keypress pressed="1">
<goto>live</goto>
</keypress>
<!-- nothing is pressed for a 3500 milliseconds, hang up the phone -->
<keypress pressed="timeout">
<hangup/>
</keypress>
</menu>
<hangup name="hangup"/>
</dialplan>
You can find more information about the IVR at CallFire Answers Page and different IVR examples are available on our public Github repository.
Check the CallFire XML page for a detailed description of all IVR tags.
The examples below show how to send an IVR call with the given dialplan:
[[code-container]] [+curl] request:
#!/usr/bin/env bash
curl -u username:password -H "Content-Type:application/json" -X POST -d '
[
{
"phoneNumber":"12135551100",
"attributes":
{
"external_user_id":"45450007002"
},
"dialplanXml":"<dialplan name=\"Root\"> <amd> <live> <goto>live</goto> </live> <machine> <goto>hangup</goto> </machine> </amd> <menu maxDigits=\"1\" timeout=\"3500\" name=\"live\"> <play type=\"tts\" voice=\"female1\" name=\"play_code\">Hello, your one-time code is 2 5 1 7, press 1 to repeat.</play> <keypress pressed=\"1\"> <goto>live</goto> </keypress> <keypress pressed=\"timeout\"> <hangup/> </keypress> </menu> <hangup name=\"hangup\"/> </dialplan>"
}
]' "https://api.callfire.com/v2/calls"
response:
{
"items": [
{
"id": 13394,
"fromNumber": "12135551189",
"toNumber": "12135551100",
"state": "READY",
"campaignId": 10,
"batchId": 6,
"contact": {
"id": 4096,
"homePhone": "12135551100"
},
"attributes": {
"external_user_id":"45450007002"
},
"inbound": false,
"created": 1443373382000,
"modified": 1443373382000,
"agentCall": false
}
]
}
[-curl]
[+java]
import com.callfire.api.client.CallfireClient;
import com.callfire.api.client.api.callstexts.model.Call;
import com.callfire.api.client.api.callstexts.model.CallRecipient;
import com.callfire.api.client.api.callstexts.model.request.SendCallsRequest;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
class ApiClientSample {
public static void main(String[] args) {
CallfireClient client = new CallfireClient("api_login", "api_password");
CallRecipient r1 = new CallRecipient();
r1.setPhoneNumber("12135551100");
r1.setDialplanXml(buildDialplanXml());
r1.getAttributes().put("external_user_id", "45450007002");
List<CallRecipient> recipients = Arrays.asList(r1);
SendCallsRequest request = new SendCallsRequest().create()
.recipients(recipients)
.build();
List<Call> calls = client.callsApi().send(request);
}
private static String buildDialplanXml() {
return
"<dialplan name=\"Root\"> "
+ "<!-- answering machine detection --> "
+ "<amd> "
+ " <!-- if call is answered by human go to live menu --> "
+ " <live> "
+ " <goto name=\"live\">Live</goto> "
+ " </live> "
+ " <!-- hangup if answering machine detected --> "
+ " <machine> "
+ " <goto>hangup</goto> "
+ " </machine> "
+ "</amd> "
+ " <menu maxDigits=\"1\" timeout=\"3500\" name=\"live\"> "
+ " <!-- play text message with secure code --> "
+ " <play type=\"tts\" voice=\"female1\" name=\"play_code\">Hello, your one-time code is 2 5 1 7, press 1 to repeat.</play>"
+ " <keypress pressed=\"1\"> "
+ " <goto>live</goto> "
+ " </keypress> "
+ " <keypress pressed=\"timeout\"> "
+ " <hangup/> "
+ " </keypress> "
+ " </menu> "
+ " <hangup name=\"hangup\"/> "
+ "</dialplan> ";
}
}
[-java]
[+csharp]
using System.Collections.Generic;
using CallfireApiClient;
using CallfireApiClient.Api.CallsTexts.Model;
using CallfireApiClient.Api.Common.Model.Request;
public class ApiClientSample
{
public static void Main(string[] args)
{
var client = new CallfireClient("api_login", "api_password");
var request = new SendCallsRequest()
{
Recipients = new List<CallRecipient> {
new CallRecipient {
PhoneNumber = "12135551100",
Attributes = new Dictionary<string, string> {
{"external_user_id", "45450007002"}
},
DialplanXml = @"
<dialplan name=""Root"">
<!-- answering machine detection -->
<amd>
<!-- if call is answered by human go to live menu -->
<live>
<goto>live</goto>
</live>
<!-- hangup if answering machine detected -->
<machine>
<goto>hangup</goto>
</machine>
</amd>
<menu maxDigits=""1"" timeout=""3500"" name=""live"">
<!-- play text message with secure code -->
<play type=""tts"" voice=""female1"" name=""play_code"">Hello, your one-time code is 2 5 1 7, press 1 to repeat.</play>
<keypress pressed=""1"">
<goto>live</goto>
</keypress>
<keypress pressed=""timeout"">
<hangup/>
</keypress>
</menu>
<hangup name=""hangup""/>
</dialplan>
"
}
}
};
IList<Call> calls = client.CallsApi.Send(request);
}
}
[-csharp]
[+js]
'strict'
const CallfireClient = require('callfire-api-client-js');
const client = new CallfireClient('api-login', 'api-password');
client.ready(() => {
client.calls.sendCalls({
body: [
{
phoneNumber: '12135551100',
attributes: {
external_user_id: '45450007002'
},
dialplanXml: '<dialplan name=\"Root\"> <amd> <live> <goto>live</goto> </live> <machine> <goto>hangup</goto> </machine> </amd> <menu maxDigits=\"1\" timeout=\"3500\" name=\"live\"> <play type=\"tts\" voice=\"female1\" name=\"play_code\">Hello, your one-time code is 2 5 1 7, press 1 to repeat.</play> <keypress pressed=\"1\"> <goto>live</goto> </keypress> <keypress pressed=\"timeout\"> <hangup/> </keypress> </menu> <hangup name=\"hangup\"/> </dialplan>'
}
]
})
.then((response) => {
console.log(response.obj);
})
.catch((err) => {
console.log('request error ' + err.data);
});
},
(clientError) => {
console.log('client error ' + clientError);
}
);
[-js]
[+python]
from callfire.client import CallfireClient
client = CallfireClient('api-login', 'api-password')
response = client.calls.sendCalls(
body=[
{
'phoneNumber': '12135551100',
'attributes': {
'external_user_id': '45450007002'
},
'dialplanXml': '<dialplan name=\"Root\"> <amd> <live> <goto>live</goto> </live> <machine> <goto>hangup</goto> </machine> </amd> <menu maxDigits=\"1\" timeout=\"3500\" name=\"live\"> <play type=\"tts\" voice=\"female1\" name=\"play_code\">Hello, your one-time code is 2 5 1 7, press 1 to repeat.</play> <keypress pressed=\"1\"> <goto>live</goto> </keypress> <keypress pressed=\"timeout\"> <hangup/> </keypress> </menu> <hangup name=\"hangup\"/> </dialplan>'
}
]
).result()
# see sample JSON response for this API
# on 'curl' samples tab
print(response)
[-python]
[+php]
<?php
class ApiClientSample {
public static function main() {
$client = \CallFire\Api\DocumentedClient::createClient("login", "password");
$request = $client->sendCalls();
$body = '[
{
"phoneNumber":"12135551100",
"attributes":
{
"external_user_id":"45450007002"
},
"dialplanXml":"<dialplan name=\"Root\"> <amd> <live> <goto>live</goto> </live> <machine> <goto>hangup</goto> </machine> </amd> <menu maxDigits=\"1\" timeout=\"3500\" name=\"live\"> <play type=\"tts\" voice=\"female1\" name=\"play_code\">Hello, your one-time code is 2 5 1 7, press 1 to repeat.</play> <keypress pressed=\"1\"> <goto>live</goto> </keypress> <keypress pressed=\"timeout\"> <hangup/> </keypress> </menu> <hangup name=\"hangup\"/> </dialplan>"
}
]';
$request->getOperationConfig()->setBodyParameter($body);
$result = $client->request($request);
$json = json_decode($result->getBody());
}
}
ApiClientSample::main();
[-php]
[[/code-container]]
See Send Calls API for detailed information about accepted parameters and responses.
You can always subscribe your service to receive notifications from CallFire after the call or text is delivered. Check webhooks guide for more information about CallFire Webhooks.