Twilioにおける認証(TwilioからのRequestデータ検証)について

Twilioは、

電話する→Twilioが電話番号にひも付けられたURLをリクエストする

という仕組みになっています。
Twilioはインターネット経由でリクエストしてきますので、リクエストを受けるアプリケーション側からすると、セキュリティ的にかなりの脅威です。対処しなければなりません。

対処の方法として以下のものがあります。

    1. Basic(基本)認証を使う
    2. アプリ側で対処する

前に作ったTwilio-MiniCCでは、Basic(基本)認証を前提にしていました。Twilio設定画面の電話番号のURL登録のところで、

http://A:B@C/D/index.php
A: Basic認証のユーザ名
B: Basic認証のパスワード
C: Webサーバのドメイン名
D: アプリを置いた場所

としてあげれば、基本認証がかかります。これでも十分かもしれません。

が、Runa-CCAはWebクライアント機能と、Twilioから呼び出されるコールフロー機能の2つを持っています。そして、PHPマイクロフレームワークSlimを使って、URLをリライトしてルーティングしていて、URLをWebクライアント機能とコールフロー機能とで共用していたため、Basic認証は使いづらいものでした(コールフロー側のみならず、Webクライアント側にもBasic認証がかかってしまう)。そこで、暫定策として、Runa-CCAのバージョン0.8では、Requestで送られてくるAccountSidを使って認証をかけていました。

見落とししていたのですが、Twilioにはもう一つの方法があります。「Validating Requests are coming from Twilio」です(日本語版もあります)。Twilioのダッシュボードに行くと得られるAUTH TOKENと、Requestで送られる値とをハッシュした値を、Twilioがヘッダーに付けてくれます。Requestを受けるアプリ側でも同じように値をハッシュして、それがTwilioの送るハッシュと値が合っていれば、そのRequestはTwilioから送られたものだと判定できます。

具体的なコーディング方法はこちらに書いてありますが、誤解を招く記載です。TwilioはPOSTデータ全てを使ってハッシュ値を算出するので、検証する側もPOSTデータ全てを使わなければなりません。$validator->validate()の3つ目の引数には、POSTデータをそのまま入れればよろしい。

Slimを使ってサンプルを作ってみましたので、公開します。

これを、

<?php
namespace Sample;

require '../vendor/autoload.php'; 

$app = \Slim\Slim::getInstance();
$params = $app->request->params();

$result = validateTwilioRequest($app, $params);

とすればTrue/Falseが返ってくるはずです。
ちなみに、Runa-CCAのVersion 1.0では、\Runa_CCA\Model\Twilioクラスに実装されています。コメントにミスがあったのと、ちょっと余計な処理しているので、別途直さなくては。あうあう。

ご参考まで。

Leave a Reply

Your email address will not be published.