All requests Plivo makes to your server URLs include X-Plivo-Signature-V3
and X-Plivo-Signature-V3-Nonce
HTTP headers. To validate a request and to verify that it originated from Plivo, you must generate a signature at your end and check that it matches the X-Plivo-Signature-V3
parameter in the HTTP header. Read more about signature validation.
Plivo SDKs provide methods to compute and verify X-Plivo-Signature-V3
.
uri string | The callback that you want to validate. This uri can be answer_url, url (message callback), message_url, callback_url, action_url, or hangup_url. |
nonce string | A randomly generated string used to verify requests. You can get the nonce from the event details posted to your callback. |
X-Plivo-Signature-V3 or X-Plivo-Signature-Ma-V3 string | You can get these values from the event details posted to your callback. |
auth_token string | Your account Auth Token, which you can get from the overview screen of the Plivo console. |
true
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
from flask import Flask, request, make_response, url_for
import plivo
from urllib.parse import urlparse, parse_qs
from plivo import utils
from plivo import plivoxml
app = Flask(__name__)
@app.route('/speak/', methods=['GET', 'POST'])
def validate_signature():
signature = request.headers.get('X-Plivo-Signature-V3', 'signature')
nonce = request.headers.get('X-Plivo-Signature-V3-Nonce', '12345')
url = url_for('validate_signature', _external=True)
auth_token = "<auth_token>"
method = request.method
if method == 'GET':
valid = plivo.utils.validate_v3_signature(
method, url, nonce, auth_token, signature)
else:
params = request.get_json()
valid = plivo.utils.validate_v3_signature(
method, url, nonce, auth_token, signature, params)
print(valid)
r = plivoxml.ResponseElement()
speak_params = {
'loop': '3'
}
r.add(plivoxml.SpeakElement("Hello, from Plivo", **speak_params))
response = make_response(r.to_string())
response.headers["Content-type"] = "text/xml"
print(r.to_string())
return response
if __name__ == "__main__":
app.run(host='0.0.0.0', debug=True)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
require 'sinatra'
require 'rubygems'
require 'plivo'
include Plivo
include Plivo::XML
get '/speak/' do
auth_token = "<auth_token>"
signature = headers.fetch("X-Plivo-Signature-V3", "signature")
nonce = headers.fetch("X-Plivo-Signature-V3-Nonce", "12345")
url = request.url
method = "GET"
output = Plivo::Utils.valid_signatureV3?(url, nonce, signature, auth_token, method)
puts output
response = Response.new
response.addSpeak("Hello, Welcome to Plivo")
xml = PlivoXML.new(response)
content_type 'text/xml'
return xml.to_s
end
post '/speak/' do
auth_token = "<auth_token>"
signature = headers.fetch("X-Plivo-Signature-V3", "signature")
nonce = headers.fetch("X-Plivo-Signature-V3-Nonce", "12345")
url = request.url
method = "POST"
output = Plivo::Utils.valid_signatureV3?(url, nonce, signature, auth_token, method, params)
puts output
response = Response.new
response.addSpeak("Hello, Welcome to Plivo")
xml = PlivoXML.new(response)
content_type 'text/xml'
return xml.to_s
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
let express = require('express');
let app = express();
app.set('port', (process.env.PORT || 5000));
app.use(express.static(__dirname + '/public'));
app.all('/speak/', function (request, response) {
let headers = request.headers;
console.log(headers);
let signature = request["X-Plivo-Signature-V3"];
let nonce = request["X-Plivo-Signature-V3-Nonce"];
if (!signature) {
signature = "signature";
}
if (!nonce) {
nonce = "12345";
}
let url = request.url;
let auth_token = "<auth_token>";
console.log(signature, nonce);
let method = request.method;
let validate;
if (method == "GET") {
validate = plivo.validateV3Signature(method, url, nonce, auth_token, signature);
} else {
let params = request.body;
validate = plivo.validateV3Signature(method, url, nonce, auth_token, signature, params);
}
console.log(validate);
let r = plivo.Response();
r.addSpeak("Hello from Plivo");
console.log(r.toXML());
response.set({
'Content-Type': 'text/xml'
});
response.end(r.toXML());
});
app.listen(app.get('port'), function () {
console.log('Node app is running on port', app.get('port'));
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<?php
require 'vendor/autoload.php';
use Plivo\Exceptions\PlivoValidationException;
use Plivo\Util\v3SignatureValidation;
use Plivo\XML\Response;
if (preg_match('/speak/', $_SERVER["REQUEST_URI"])) {
$auth_token = "<auth_token>";
$signature = @$_SERVER["X-Plivo-Signature-V3"] ?: 'signature';
$nonce = @$_SERVER["X-Plivo-Signature-V3-Nonce"] ?: 'nonce';
$url = 'http' . (isset($_SERVER['HTTPS']) ? 's' : '') . '://' . "{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}";
$method = $_SERVER['REQUEST_METHOD'];
$SVUtil = new v3SignatureValidation();
if ($method == "GET") {
try {
$valid = $SVUtil->validateV3Signature($method, $url, $nonce, $auth_token, $signature);
} catch (PlivoValidationException $e) {
echo("error");
}
} else {
$body = file_get_contents("php://input");
$params = json_decode($body, true);
try {
$valid = $SVUtil->validateV3Signature($method, $url, $nonce, $auth_token, $signature, $params);
} catch (PlivoValidationException $e) {
echo("error");
}
}
echo $valid;
$body = 'Hi, Calling from Plivo';
$attributes = array(
'loop' => 3,
);
$r = new Response();
$r->addSpeak($body, $attributes);
echo($r->toXML());
} else {
echo "<p>Welcome to Plivo</p>";
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
package plivoexample;
import java.io.IOException;
import java.net.URLDecoder;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import com.plivo.helper.exception.PlivoException;
import com.plivo.helper.xml.elements.Message;
import com.plivo.helper.xml.elements.PlivoResponse;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import com.plivo.helper.util.*;
public class validateSignature extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String auth_token = "<auth_token>";
String signature = req.getHeader("X-Plivo-Signature-V3");
String nonce = req.getHeader("X-Plivo-Signature-V3-Nonce");
String url = req.getRequestURL().toString();
String method = req.getMethod();
if(method == "GET") {
try {
Boolean isValid = Utils.validateSignatureV3(url, nonce, signature, auth_token, method);
System.out.println("Valid : " + isValid);
} catch (PlivoException e) {
e.printStackTrace();
}
}
else{
try {
Map<String, String> params = req.getParameterMap();
Boolean isValid = Utils.validateSignatureV3(url, nonce, signature, auth_token, method, params);
System.out.println("Valid : " + isValid);
} catch (PlivoException e) {
e.printStackTrace();
}
}
PlivoResponse response = new PlivoResponse();
Speak spk = new Speak("Hello, Welcome to Plivo");
try {
response.append(spk);
System.out.println(response.toXML());
resp.addHeader("Content-Type", "text/xml");
resp.getWriter().print(response.toXML());
} catch (PlivoException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception {
String port = System.getenv("PORT");
if(port==null)
port ="8000";
Server server = new Server(Integer.valueOf(port));
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/");
server.setHandler(context);
context.addServlet(new ServletHolder(new validateSignature()),"/speak");
server.start();
server.join();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
using System;
using System.Collections.Generic;
using System.Diagnostics;
using RestSharp;
using Plivo.XML;
using Plivo;
using Nancy;
namespace plivo_dotnet_app
{
public sealed class Program : NancyModule
{
public Program()
{
Get("/speak/", x =>
{
string signature = Request.Headers["X-Plivo-Signature-V3"].ToString();
string nonce = Request.Headers["X-Plivo-Signature-V3_Nonce"].ToString();
string auth_token = "<auth_token>";
string method = Request.Method;
string url = Request.Url;
bool valid;
Dictionary<string, string> parameters = new Dictionary<string, string>();
valid = Plivo.Utilities.XPlivoSignatureV3.VerifySignature(url, nonce, signature, auth_token, method);
Debug.WriteLine("Valid : " + valid);
Plivo.XML.Response resp = new Plivo.XML.Response();
resp.AddSpeak("Hello, Welcome to Plivo", parameters);
Debug.WriteLine(resp.ToString());
var output = resp.ToString();
var res = (Nancy.Response) output;
res.ContentType = "text/xml";
return res;
});
Post<Response>("/speak/", x =>
{
string signature = Request.Headers["X-Plivo-Signature-V3"].ToString();
string nonce = Request.Headers["X-Plivo-Signature-V3_Nonce"].ToString();
string auth_token = "<auth_token>";
string method = Request.Method;
string url = Request.Url;
bool valid;
Dictionary<string, string> parameters = new Dictionary<string, string>();
parameters = Request.Form;
valid = Plivo.Utilities.XPlivoSignatureV3.VerifySignature(url, nonce, signature, auth_token, method, parameters);
Debug.WriteLine("Valid : " + valid);
Plivo.XML.Response resp = new Plivo.XML.Response();
resp.AddSpeak("Hello, Welcome to Plivo", parameters);
Debug.WriteLine(resp.ToString());
var output = resp.ToString();
var res = (Nancy.Response) output;
res.ContentType = "text/xml";
return res;
});
}
static void Main(string[] args)
{
var p = new Program();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"reflect"
"unsafe"
"github.com/plivo/plivo-go/v7"
"github.com/plivo/plivo-go/v7/xml"
"github.com/sirupsen/logrus"
)
type Message struct {
Id string `json:"id"`
Name string `json:"name"`
}
func BytesToString(b []byte) string {
bh := (*reflect.SliceHeader)(unsafe.Pointer(&b))
sh := reflect.StringHeader{bh.Data, bh.Len}
return *(*string)(unsafe.Pointer(&sh))
}
func speak(w http.ResponseWriter, request *http.Request) {
url := request.Host + request.RequestURI
signature := request.Header.Get("X-Plivo-Signature-V3")
nonce := request.Header.Get("X-Plivo-Signature-V3-Nonce")
method := request.Method
authToken := "<auth_token>"
var valid bool
if method == "GET" {
valid = plivo.ValidateSignatureV3(url, nonce, method, signature, authToken)
} else {
parameters := make(map[string]string)
b, err := ioutil.ReadAll(request.Body)
defer request.Body.Close()
if err != nil {
http.Error(w, err.Error(), 500)
return
}
var msg Message
err = json.Unmarshal(b, &msg)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
var inInterface map[string]interface{}
inrec, _ := json.Marshal(msg)
json.Unmarshal(inrec, &inInterface)
for field, val := range inInterface {
parameters[field] = val.(string)
}
w.Header().Set("content-type", "text/xml")
valid = plivo.ValidateSignatureV3(url, nonce, method, signature, authToken, parameters)
}
logrus.Info(valid)
response := xml.ResponseElement{
Contents: []interface{}{
new(xml.SpeakElement).
AddSpeak("Go Green, Go Plivo."),
},
}
fmt.Fprintf(w, response.String())
}
func main() {
http.HandleFunc("/speak/", speak)
http.ListenAndServe(":5000", nil)
}