最近はログインID/PW方式だけではセキュリティ的に厳しいと言うことで様々な認証方式が使われています。
SMSを使ったSMS認証もあるのですが、最近はOTP(One Time Password)を用いた認証方式が増えてきています。
スクウェア・エニックスのOTPはネットゲームを行うユーザーには有名でしょうか
目次
なんかめちゃくちゃ大変そう…
専用サーバーが必要とか色々大変そうに思いますよね。ところがGoogleはこのあたりの仕様を公開しており、それを使ったライブラリが公開されているので簡単に実装ができます。
スマホアプリで認証システムをダウンロードする
Googleが公開している「Google 認証システム」を使用します。Android版はこちら
iOS版はこちら
「PHPGangsta/GoogleAuthenticator」をインストールする
使うライブラリは「PHPGangsta/GoogleAuthenticator」と呼ばれるものです。インストールです方法ですが、以前に導入した「Composer」を使います。
1 2 |
composer show --available phpgangsta/googleauthenticator composer require --prefer-dist phpgangsta/googleauthenticator:dev-master |
これでインストールができます。
めちゃくちゃ簡単ですね。
PHPで実装する
それでは実装します。最低限の実装ですのでバリデーションチェックとかは入れてません。
処理も簡単なので最初から全部出します。
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 |
require_once __DIR__ . '/../vendor/autoload.php'; session_start(); // Google認証システムで表示される認証名です $auth_title = "2段階認証"; $secret = ""; $ga = new PHPGangsta_GoogleAuthenticator(); // 本来はユーザーごとにsecretを発行してDBなどに保存し、最初のログイン処理で$secretを呼び出す。 // ない場合は「$ga->createSecret();」で生成して保存します。 if(isset($_SESSION["secret"])){ $secret = $_SESSION["secret"]; } if($secret == ""){ $secret = $ga->createSecret(); $_SESSION["secret"] = $secret; } // QRコードのURLを生成する $qrCodeUrl = $ga->getQRCodeGoogleUrl($auth_title, $secret); $checkResult = false; $is_valid = false; $oneCode = ""; // コードを入力された場合はvarifyCodeで認証する。 if(isset($_POST["oneCode"]) && isset($_POST["oneCode"]) != ""){ $is_valid = true; $oneCode = $_POST["oneCode"]; $checkResult = $ga->verifyCode($secret, $oneCode, 2); // 2 = 2*30sec clock tolerance } |
大前提として「2段階認証」と言うことで本当はログイン後にこの処理を入れてください。
流れとしては「通常のログイン画面」→「ログイン完了後にOTP認証」→「認証後に画面遷移」となります。
HTML表示部は以下の感じです。
見栄えをよくするためbootstrapを使ってますが、何でもOKです
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 |
<!doctype html> <html lang="ja"> <head> <!-- Required meta tags --> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- Bootstrap CSS --> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous"> <title>2段階認証</title> </head> <body> <div class="container"> <?php if($is_valid): ?> <?php if($checkResult): ?> <div class="alert alert-success" role="alert"> 認証OK </div> <?php else: ?> <div class="alert alert-warning" role="alert"> 認証NG </div> <?php endif; ?> <?php else: ?> <img src="<?php echo $qrCodeUrl; ?>" class="img-thumbnail"> <?php endif; ?> <form action="./" method="POST"> <div class="form-group"> <label for="exampleInputPassword1">パスフレーズ</label> <input type="text" class="form-control" id="exampleInputPassword1" name="oneCode" value="<?php echo $oneCode; ?>" placeholder="6桁" maxlength="6" minlength="6"> </div> <button type="submit" name="cmd" value="confirm" class="btn btn-primary">認証</button> </form> <?php echo "Secret is: ".$secret."\n\n"; ?> </div> <!-- Optional JavaScript; choose one of the two! --> <!-- Option 1: Bootstrap Bundle with Popper --> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script> <!-- Option 2: Separate Popper and Bootstrap JS --> <!-- <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.2/dist/umd/popper.min.js" integrity="sha384-IQsoLXl5PILFhosVNubq5LC7Qb9DXgDA9i+tQ8Zj3iwWAwPtgFTxbJ8NT4GN1R8p" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.min.js" integrity="sha384-cVKIPhGWiC2Al4u+LWgxfKTRIcfu0JTxR+EQDz/bgldoEyl4H0zUF0QKbrJ0EcQF" crossorigin="anonymous"></script> --> </body> </html> |
$qrCodeUrlを<img >タグで指定すると、QRコードが生成されます。
このQRコードを「Google認証システム」で読み取ると、6桁のコードが表示されるので、そのコードを入力してもらい、認証ボタンを押すことで判定します。
ここでは「認証OK」「認証NG」と表示していますが、実際はPHP側で判定を行い、処理を行います。
実際にどういう場面で使う?
実装は簡単ですし、導入するだけでログインセキュリティは上がると思います。今ある会員ログインシステムがあるとすると、設定画面から「2段階認証」機能を作り
ONにした場合は$secretを発行してQRコードを表示し、「Google認証システム」に登録して
認証できたら使用可能という感じでしょうか
私が思った懸念事項は2点
- スマホサイトやアプリの場合、アプリやブラウザと「Google認証システム」を行ったり来たりするので、少しめんどくさくなる
- 機種変更などで「Google認証システム」を初期化した場合、2段階認証が行えなくなり、解除もできなくなる
一応前述のスクウェア・エニックスのOTPでは「強制解除コード」を発行して、これを入力することで2段階認証を解除することができます。
解除コードを忘れた場合は運営に問い合わせることで解除することができますが、これは時間がかかりますね。
とはいえ、使い方によっては実装の割にログインセキュリティは飛躍的に上がるので、検討の価値はありそうです。
YoutubeChannelのご紹介
同様の内容を、動画でご覧になれます。https://youtu.be/D8HFYftxzUc