Twilioは、
電話する→Twilioが電話番号にひも付けられたURLをリクエストする
という仕組みになっています。
Twilioはインターネット経由でリクエストしてきますので、リクエストを受けるアプリケーション側からすると、セキュリティ的にかなりの脅威です。対処しなければなりません。
対処の方法として以下のものがあります。
- Basic(基本)認証を使う
- アプリ側で対処する
前に作った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クラスに実装されています。コメントにミスがあったのと、ちょっと余計な処理しているので、別途直さなくては。あうあう。
ご参考まで。