2021.02.15
まとめ
この記事を読んだ人へのオススメ
-
2022.02.07
-
2022.02.14
-
2020.06.01
-
2022.03.14
Twilioブログ
2021.02.15
こんにちは、katsu.tです。
企業のセキュリティ意識が高まっている昨今、顧客が安全にアカウントを利用できるように多くのサービスが二要素認証を取り入れています。
なかでもSMSや電話を使った音声での二要素認証機能は、簡単にアカウントが発行できるメールでの二要素認証よりも確実に本人認証できると注目されています。
そこで今回の記事では、電話番号を用いた「二要素認証API」を、TwilioとPHPのフレームワークであるLaravelを使って作成する方法をご紹介いたします。
※二段階認証と二要素認証の違いについては、こちらの記事をご覧ください。
TwilioとLaravelを用いて作るAPIには、「認証コードを送信するAPI」と「送信された認証コードを検証するAPI」の2種類があります。
SMSまたは電話を使って、対象の電話番号に認証コードを送信します。
エンドポイント
・api/verifications
パラメータ
パラメータ名 | 役割 | 設定値 |
to | 認証コードを送信する電話番号 | 例:+8190xxxxxxxx |
channel | 送信するチャネル | sms/voice |
curl -X POST http://localhost:8000/api/verifications \ --data-urlencode 'to=+8190xxxxxxxx' \ --data-urlencode 'channel=sms'
送信された認証コードの検証に利用します。
エンドポイント
・api/validate
パラメータ
パラメータ名 | 役割 | 設定値 |
to | 認証コードを送信した電話番号 | 例:+8190xxxxxxxx |
code | 検証する認証コード | 例:123456 |
curl -X POST http://localhost:8000/api/validate \ --data-urlencode 'to=+8190xxxxxxxx' \ --data-urlencode 'code=123456'
まずは新しいLaravelプロジェクトを作成し、作成したフォルダに移動します。
$ composer create-project laravel/laravel verify-system $ cd verify-system
次に、フォルダ内にある".envファイル"を修正していきます。
.envファイルの一番下にTwilioの情報を追記します。コメント部分は削除して追記してください。
TWILIO_SID=ACxxxxxxxxxxxxxxxx // twilioコンソールから確認することができます。 TWILIO_TOKEN=xxxxxxxxxxxxxxxxxx // twilioコンソールから確認することができます。 TWILIO_FROM=+14xxxxxxx // twilioで購入したアメリカ番号を設定します。 TWILIO_FROM_VOICE=+8150xxxxxxx // twilioで購入した日本番号を設定します。
続いてDBの設定を行いましょう。
本ブログでは、依存性の少ない軽量のRDB SQliteを利用します。
まず.envファイルのDBの項目を修正します。
修正前 DB_CONNECTION=mysql // 修正 DB_HOST=127.0.0.1 // 削除 DB_PORT=3306 // 削除 DB_DATABASE=laravel // 削除 DB_USERNAME=root // 削除 DB_PASSWORD= // 削除 ↓ 修正後 DB_CONNECTION=sqlite
sqlite用のDBファイルをdatabaseフォルダ内に作成します。
$ touch database/database.sqlite
DBの設定が完了したら、マイグレーションの作成を行います。
$ php artisan make:migration create_verifies_table
database/migrations/日付_create_verify_table.phpのpublic functions up()の中身を以下ソースコードで上書きします。
public function up() { Schema::create('verifies', function (Blueprint $table) { $table->id(); $table->string('to'); // 送信先 $table->string('code'); // 認証コード $table->string('status'); // 送信ステータス $table->timestamps(); }); }
DBのマイグレートを行います。
$ php artisan migrate
TwilioのSDKをインストールします。
$ composer require twilio/sdk
※次のようなエラーが表示されたら以下コマンドをお試しください。
Fatal error: Allowed memory size of 1610612736 bytes exhausted (tried to allocate 4096 bytes) in phar:///usr/local/Cellar/composer/1.8.3/bin/composer/src/Composer/DependencyResolver/RuleWatchGraph.php on line 52 Check https://getcomposer.org/doc/articles/troubleshooting.md#memory-limit-errors for more info on how to handle out of memory errors.
$ COMPOSER_MEMORY_LIMIT=-1 composer require twilio/sdk
設定が完了したら、いよいよAPI作成のフェーズに入ります。
Programmable SMS と Programmable Voice を利用し、認証コードを送信する部分を作っていきましょう。
まず、Modelを作成します。
$ php artisan make:model Verify
続いて、Controllerを作成します。
$ php artisan make:controller VerificationsController
作成できたら、以下ソースコードで app/Http/Controller/VerificationsController.phpを上書きします。
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Models\Verify; use Twilio\Rest\Client; class VerificationsController extends Controller { // 認証コードの送信 public function verifications(Request $request) { $code = $this->generateCode(6); $verify = new Verify; $verify->to = $request->to; $verify->code = $code; $result = $this->sendCode($code,$request->channel,$request->to); if($result) { $verify->status = 'send'; $verify->save(); return response()->json([ 'message' => 'send success' ],200); } else { return response()->json([ 'message' => 'send failed' ],400); } } // 認証コード生成 private function generateCode($length) { $max = pow(10, $length) - 1; $rand = random_int(0, $max); $code = sprintf('%0'. $length. 'd', $rand); return $code; } // 認証コード送信 private function sendCode($code,$channel,$to) { $client = new Client(env('TWILIO_SID'),env('TWILIO_TOKEN')); if($channel == 'sms') { $client->messages->create( $to, [ 'from' => env( 'TWILIO_FROM' ), 'body' => 'あなたの認証コードは '.$code.' です。', ]); return true; } else if($channel == 'voice'){ $client->calls->create( $to, env( 'TWILIO_FROM_VOICE' ), // from [ "twiml" => "<Response><Say language='ja-Jp'>あなたの認証コードは".join(',',str_split($code))."です。</Say></Response>" ]); return true; } else { return false; } } }
続いて、routes/api.phpに認証コード送信APIを追加します。
use App\Http\Controllers\VerificationsController; ~~~ 中略 ~~~ Route::post('/verifications',[VerificationsController::class,'verifications']);
以上で認証コード送信APIの実装は完了です。
次に、送信した認証コードの検証APIを作っていきます。
以下ソースコードを app/Http/Controller/VerificationsController.php に追記します。
public function verificationCheck(Request $request) { // 送信先と認証コードを元に送信済みで未検証なレコードを取得 $verifies = Verify::where('to',$request->to)->where('code',$request->code)->whereNotIn('status',['verified'])->get(); // レコードがあれば認証成功 if(count($verifies) == 1) { $verify = $verifies->first(); $verify->status = 'verified'; $verify->save(); return response()->json([ 'message' => 'verification success' ],200); } else { // レコードがなければ認証失敗 return response()->json([ 'message' => 'verification failuer' ],401); } }
続いて、routes/api.php に認証コード送信APIを追加します。
Route::post('/validate',[VerificationsController::class,'verificationCheck']);
以上で検証APIの作成は完了です。
APIの作成が完了したら、作ったAPIが正しく機能しているかをテストしていきましょう。
まずは、作成したサーバーを起動します。
$ php artisan serve
起動後、APIを試します。
$ curl -X POST http://localhost:8000/api/verifications \ --data-urlencode 'to=+8190xxxxxxxx' \ --data-urlencode 'channel=sms'
toに設定した電話番号にSMSが届いていることを確認しましょう。
※SMSが受信できなかった場合は、こちらのFAQをご確認ください。
無事にSMSが届いたら、送信された認証コードをAPIで検証します。
$ curl -X POST http://localhost:8000/api/validate \ --data-urlencode 'to=+8190xxxxxxxx' \ --data-urlencode 'code=209336'
200が返却されたら、認証コードの検証成功です。
まとめ
今回の記事では、独自で「二要素認証API」を作成する方法をご紹介いたしました。
すでにメールでの二要素認証を導入していて、SMSや電話を使った音声での二要素認証についてはこれから導入を検討していく……といった方々の参考になれば幸いです。
またTwilioでは、今回ご紹介した内容に近い二要素認証が簡単に導入できるAPIを2つご用意しております。電話番号を用いた認証を低コストで導入できますので、二要素認証の導入自体がまだの方はぜひご検討ください。
・Twilio Verifyを使った二要素認証、二段階認証の実装方法
・Twilio Authyを用いた二要素認証、二段階認証の実装方法
前職でiOS、Androidのネイティブアプリケーション開発、AngularやLaravelを用いたウェブアプリケーション開発に従事。KDDIウェブコミュニケーションズではTwilioの最新情報の発信やTwilioを用いた地域課題解決を担当。 個人では、Google Developer Group Tokyoのオーガナイザーを務める。
Twitter:https://twitter.com/chiino58
2022.05.18
2022.04.18
2022.07.01
2022.08.23
2022.10.11
2022.05.24
2022.09.20
2022.11.02
2022.10.11
2022.09.20
2022.08.23