9
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

OpenAMでQRコード認証を実現できるか試してみる

Last updated at Posted at 2018-12-11

はじめに

 新入社員のアカウントの初期パスワードは、どのように設定・入力してもらうと良いでしょうか。

 初期パスワードを設定する際、誕生日にアルファベットを足したものや社員番号など、類推可能なものにするのは危険です。ランダムな文字列にする場合でも、短いものにしてしまうと、ブルートフォースアタックの脅威にさらされてしまうかもしれません。それでは長いランダム文字列にした場合は…、今度は利用開始の障壁になってしまいそうです。

 解決案として、「長いランダム初期パスワードをQRコード化して送付し、初回ログイン時はQRコードをかざすことで認証してもらう。(その後、強制的にパスワードを変更してもらう)」、というのはどうでしょうか。

 幸い近年、QRコードを扱うJavascriptライブラリを公開してくださってる、素晴らしい方々がいらっしゃいます。弊社も取り扱っております認証基盤OSS「OpenAM」では色々カスタマイズが可能なので、ライブラリを組み込んでQRコード認証の実現を試してみます。

(注: 本記事は、あくまで簡易的に試してみるというものです。実際にご利用される場合は、各自のご責任の下で実施くださいませ。)

実施

OpenAM のインストールと初期設定

 まず、OSSTech版のOpenAM 13をインストールして初期設定しておきます。ここは今回の本題ではないので、詳細は割愛します。
(OpenAM 13がお手元にない場合でも、読み取ったQRコードの格納先となるテキストフィールドなりをご用意いただければ、QRコード読み取りのテストは可能です。)

 次にですが、スマホでもカメラを起動してQRコードを読めるようにするためには、httpsでのアクセスにする必要があるようです。このため、あらかじめhttps化の対応もしておきます。ここも、詳細は割愛します。

 ここでログイン画面にアクセスしてみると、OpenAMでは初期状態でデータストア認証の画面が出てくるようになってます。普通にIDとパスワードを入れるというものでして、画面例は下図のようになります。
 これから、このパスワードのフィールドへの入力を、QRコード読み込み対応にしてみます。

QRコード読み取りライブラリの取り込み

 QRコード画像を読み取るjavascriptライブラリとして、今回は「jsqrcode」を取り込んでみます。
https://github.com/LazarSoft/jsqrcode
(Apache License 2.0)

$ mkdir <OpenAM ウェブアプリのデプロイ先>/openam/XUI/jsqrcode
$ (作成したディレクトリ内に、jsqrcodeのjs群を格納する。)

認証画面の編集

 認証画面を編集していきます。
 データストア認証の認証画面(の一部)は以下の場所にありますので、viでオープンすることにします。

$ vi <OpenAM ウェブアプリのデプロイ先>/openam/XUI/templates/openam/authn/DataStore1.html

 修正内容としては、まずHTMLの要素として以下のコードを追加します。

  <div style="text-align: center;">
    <video id="video_id" width="300" height="300" autoplay="1" playsinline></video>

    <div style="display:none">
      <canvas id="canvas_id"></canvas>
    </div>

    <div id="message_id"></div>
  </div>

 そして、以下のjavascriptコードを追加します。
 大して特別なことはしていないので、詳細はコード内コメントやコードを直接ご参照ください。

<script type="text/javascript" src="jsqrcode/grid.js"></script>
(同様にjsqrcodeのgitページに記載の通り必要なjsを全部取り込む。)

<script>
  // HTML要素群。この'idToken2'が、読み取った値の格納先
  const const_resultArea = document.getElementById('idToken2');
  const const_video = document.getElementById('video_id');
  const const_canvas = document.getElementById('canvas_id');
  const const_messageDiv = document.getElementById('message_id');

  // 連続失敗カウンタ
  let let_failureCounter = 0;

  // カメラを見つけてストリームをセット
  // (スマホで内向きカメラが選ばれないよう、外向きカメラをideal指定する)
  if (!navigator.mediaDevices.getUserMedia) {
    alert("This browser may not handle HTML5_UserMedia.  Please try other browers.");
  } else {
    navigator.mediaDevices.getUserMedia(
      { video: { facingMode: { ideal: 'environment' } }, audio: false }
    ).then(
      function(stream) { const_video.srcObject = stream; },
      function() { alert("Error... Cannot get video stream..."); }
    );
  }

  // 読み取り結果を処理。
  // (失敗の判定が雑な感じだが、ひとまずお試しとしてこれで動かす。)
  qrcode.callback = function(decodedInformation) {
    if (!decodedInformation ||
        decodedInformation === "error decoding QR Code" ||
        decodedInformation === "Failed to load the image") {
      let_failureCounter++;
      const_messageDiv.textContent = "QR Read : Failed... " + let_failureCounter;
    } else {
      let_failureCounter = 0;
      const_resultArea.value = decodedInformation;
      const_messageDiv.textContent = "QR Read : Succeeded!!";
    }
  };

  // 画像化&QRコード読み取りを1回実施
  function decodeOneTime() {
    const_canvas.setAttribute("width", const_video.videoWidth);
    const_canvas.setAttribute("height", const_video.videoHeight);
    const const_canvas_context = const_canvas.getContext('2d');
    const_canvas_context.drawImage(const_video, 0, 0, const_video.videoWidth, const_video.videoHeight);

    if (const_canvas_context) {
      qrcode.decode(const_canvas.toDataURL('image/png'));
    }
  }

  // 毎秒処理する
  setInterval(decodeOneTime, 1000);
</script>

結果

 たったこれだけで、QRコード認証の基本的なところはできてしまいました。

 利用中の画面は下図のようになります。
 QRコードをかざすと、長いパスワード文字列が読み取られ、パスワードフィールドに自動入力されます。

おわりに

 きちんと検証する必要はありますが、QRコード認証を実現できそうな感触を得ることができました。
 今回は初期ログインという目的を例示しましたが、他の目的で利用しても良いかもしれません。例えば、多要素認証における簡易的な2段階目認証として使う、とかどうでしょう。

以上です。

9
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?