ログイン時の2段階認証に使われるGoogle認証システムの「Google Authenticator」。これを使って認証システムが作れるPHPライブラリがGitHubに公開されています。
このコードを読んで「Google Authenticator」の仕組みを理解していきます。
参考URL:GitHub[ PHPGangsta/GoogleAuthenticator ]
Google Authenticator について軽く解説
Google Authenticator はGoogleの専用アプリを使って使用できる、2段階認証システムです。
サービス側で生成した秘密鍵を専用アプリに入力することで連携させると、専用アプリでその秘密鍵と結びついた6桁の数字が30秒ごとにランダムで生成し続けます。
その数字列をサービス側で入力することでメールアドレスやSMSを使わない簡単な2段階認証が設定できるシステムです。
公開されているPHPファイル
GitHubで公開されているライブラリはBSDライセンスです。
ライブラリは1つだけのファイルなのでサーバーにぶち込んで、インクルードするだけで使用できます。
それではPHPファイルを見ていきます。参照ライブラリ
createSecret メソッド
このはじめにこのメソッドが定義されているので使ってみます。
<?php
include_once "inc/googleAuthenticator.php";
$ga = new PHPGangsta_GoogleAuthenticator();
$secret = $ga->createSecret();
echo $secret; //FSGLBPGND2K6TILD
localhostで表示してみるとランダムっぽい16桁のアルファベット文字列が表示されています。ページをリロードしてみると別の文字列が生成されているのでランダム文字列のようです。
ライブラリファイルを見てみると引数が設定されていて初期値は16となっているようです。これは、ランダム文字列の桁数で、16桁から128桁まで任意に設定できるようになっています。
getCode メソッド
このメソッドは先ほど生成したランダム文字列を引数に取るようです。
まずは使ってみましょう。先ほどのコードは省略します。
<?php
...
$code = getCode($secret);
echo $code; //024151
6桁の数字が表示されました。ちなみに6桁以上の文字列を使用するとエラーとなるようですね。
コメントに「時間と文字列によって計算された数字を表示する」とあります。専用アプリで表示される数字列がこの6桁の数字になるようです。
つまりGoogle Authenticator の数字は時間とシークレット文字列で生成されていることがわかりました。
getQRCodeGoogleUrl メソッド
このメソッドはGoogle Authenticator のQRコードスキャン機能で使用できるQRコードを生成するメソッドですね。引数に$nameを設定する必要があるようです。
使用してみます。
<?php
...
$qr_code = $ga->getQRCodeGoogleUrl( 'Test', $secret );
echo $qr_code;
// https://api.qrserver.com/v1/create-qr-code/?data=otpauth%3A%2F%2Ftotp%2FTest%3Fsecret%3DJVSW7M3E2E7LL5HG&size=200x200&ecc=M
URLが表示されました。qrserverのAPIを使用してQRコードを表示するURLを生成しているようです。アクセスしてみましょう。
ちなみにURLにシークレットコードが入っていますね。今回は「JVSW7M3E2E7LL5HG」のようです。
※今回はテストとしてシークレットコードやQRコードを公開していますが、本来は絶対に人に教えてはいけません。
では、Google Authenticator に登録してみます。
QRコードを読み込むだけで簡単に追加されました。
ちなみに先ほどのgetCodeメソッドに今回のシークレットコードを引数に渡して表示してみると、やはりアプリの数字と同じ数字が表示されました。
verifycode メソッド
これはシークレットコードと表示されている数字を引数に渡すことで認証が正しいか判断してくれるメソッドのようです。
getCodeメソッドの数字と等号すれば良いように思いますが、このメソッドでは第3引数に数字を渡すことで周期で数字が更新されても誤差として計算させることができます。
<?php
...
$secret = 'JVSW7M3E2E7LL5HG';
$verify = $ga->verifyCode( $secret, '547488', 2 );
var_dump($verify); // TRUE or FALSE
第1引数にシークレットコード、第2引数に数字列を渡します。ここで数字列はStringなので注意ですね。第3引数は整数を渡すことで誤差範囲を設定することができます。初期値は1となっています。
認証に使う数字は30秒周期で更新されます。例えば、第3引数を1と設定することで、現在表示されている数字と前周期で表示されていた数字を認証してくれます。
つまり、数字入力中タイマーが更新されても30秒間の猶予があるということですね。2を渡すと1分間の猶予が設定されます。この値を大きくするほど入力までの余裕ができますが、認証対象の数字が多くなるのでセキュリティは落ちてしまうわけですね。
まとめ
以上を使ってGoogle Authenticator を利用できることがわかりました。ライブラリもとてもわかりやすくて助かります。
ただQRコード生成のコードはあくまでURLを生成するだけなので、HTTPでシークレットコードが送信されてしまうのが少し危ない気がします。
QRコードを生成するライブラリなどを使ってサーバー側でQRコードを作成するのがベストだと思います。