Latest Legacy

Validation

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.

Arguments

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.

Response

  true

Example Request

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)
}