Amazon Cognito でお手軽に作る多要素認証Webシステム

記事タイトルとURLをコピーする

こんにちは!クラウドインテグレーション部 技術1課 宮形 です。

Amazon Cognito をもちいて、お手軽に多要素認証のWebシステムを構築する検証を行いましたので、今回BLOGでご紹介したいと思います。

f:id:swx-miyagata:20220131173611p:plain

内容としては、当社先輩が過去に BLOG で紹介した内容の焼直しになりますので、ご了承ください。 blog.serverworks.co.jp

概要

「既に存在しているイントラネットのWebシステムを外部公開するにあたり多要素認証を追加する」という要件を想定しています。 利用するサービスの Amazon Cognito (コグニート 以下 Cognito と記) は、ウェブおよびモバイルアプリの認証、承認、およびユーザー管理機能を提供するAWSのマネージドサービスです。 Cognito は多要素認証の機能を有しています。IDパスワード認証に加え、携帯電話にSMSでワンタイムパスワードを受け取り多要素認証を行う環境の構築を行います。

構成図

下記のようなAWSの構成となります。Webシステムは、Windows Server IIS のデフォルトページで代用しております。 Application Load Balancer (ALB) が Cognito と連携して認証を行います。本来は ALB 配下の EC2 を複数台構成または AutoScaling で構成するべきですが、検証なので1台のみとします。

f:id:swx-miyagata:20220131175345p:plain

検証内容

注意!本BLOGでは、検証時に私が間違い設定を行ってしまいトラブルシューティングを行っている箇所をそのまま掲載しています。

AWS Cognito の設定

AWSマネージメントコンソールより「セキュリティ、ID、およびコンプライアンス」>「Cognito」を選択します。

f:id:swx-miyagata:20220131165258p:plain

「Amazon Cognito」の画面が表示されます。「ユーザープールの管理」を選択します。

f:id:swx-miyagata:20220131165417p:plain

「ユーザープール」の画面となります。「ユーザープールを作成する」をクリックします。

f:id:swx-miyagata:20220131165552p:plain

ユーザープールに名前を付けます。「プール名」欄にわかりやすい名前を入力します。 「ユーザープールをどのように作成しますか?」は「ステップに従って設定する」を選択します。

f:id:swx-miyagata:20220131165514p:plain

「エンドユーザーをどのようにサインインさせますか?」の画面となります。本検証では「Eメールアドレスおよび電話番号」>「Eメールアドレスを許可」を選択します。 「どの標準属性が必要ですか?」では「email」「phone number」を有効とします。email はユーザーがパスワードリセットする際に利用、phone number はSMSでのワンタイムパスワード受取りに利用するので必須になります。

f:id:swx-miyagata:20220131165615p:plain

「ポリシー」の画面となります。ここでは「ユーザーに自己サインアップを許可しますか?」>「管理者のみユーザーの作成を許可する」を選択します。ご利用システム要件、運用要件に応じて設定となります。

f:id:swx-miyagata:20220131165652p:plain

「多要素認証(MFA)を有効にしますか?」>「必須」、「第2の要素として何を有効にしますか?」>「SMSテキストメッセージ」、「ユーザーはどのようにしてアカウントを回復できますか?」>「Eメールのみ」、「どの属性を確認しますか?」>「Eメール」とします。こちらも、ご利用システム要件、運用要件に応じて設定となります。

f:id:swx-miyagata:20220131165722p:plain

「Amazon Congnito に対して SMS メッセージの送信を許可するロールを提供する必要があります」では、「新規ロール名」に任意の名前を設定し「ロールの作成」をクリックします。

f:id:swx-miyagata:20220131165746p:plain

「Eメールをカスタマイズしますか?」の画面では、ユーザーがパスワードリセットを行うときの本人確認のメール送信者アドレスや検証メッセージ内容などをカスタマイズできます。 今回は検証目的なので、特に設定変更はせずに次へ進みます。

f:id:swx-miyagata:20220131165832p:plain

「このユーザープールにタグを追加しますか?」の画面となります。今回の検証ではタグは不要なので、そのまま次へ進みます。

f:id:swx-miyagata:20220131165849p:plain

「ユーザーのデバイスを記憶しますか?」の画面となります。この設定を有効にすると、AWS側にユーザーが認証を行った際のデバイスキー、IPアドレス、タイムスタンプ等を記録できます。 今回の検証では「いいえ」として次へ進みます。

f:id:swx-miyagata:20220131165912p:plain

「このユーザープールへのアクセス権限があるアプリクライアントはどれですか?」の画面では、そのまま次へ進みます。この設定は後で変更します。

f:id:swx-miyagata:20220131165930p:plain

「トリガーを使用してワークフローをカスタマイズしますか?」の画面となります。Cognito の API 処理ステップ毎に、バックエンドの処理を定義することが可能です。本検証では利用しないので、そのまま次へ進みます。

f:id:swx-miyagata:20220131165954p:plain

サマリー画面で内容を確認し「プールの作成」をクリックします。

f:id:swx-miyagata:20220131170035p:plain

続けて Cognito ユーザープールの画面で「アプリクライアント」>「アプリクライアントの追加」をクリックします。

f:id:swx-miyagata:20220131170105p:plain

アプリクライアントの登録画面となります。「アプリクライアント名」に任意の名前を設定します。本検証では他設定はデフォルトのままとします。

f:id:swx-miyagata:20220131170145p:plain

アプリクライアントの登録が完了すると、「アプリクライアントID」が画面に表示されます。後で参照しますので、手元に控えておきます。

f:id:swx-miyagata:20220131170218p:plain

続けて Cognito ユーザープールの画面で「アプリの統合」>「アプリクライアントの設定」をクリックします。 下記のように設定します。ここでのアプリとは、後ほど設定する AWS の ALB (ロードバランサー)となります。AWS の仕様に合わせて設定します。

Application Load Balancer を使用してユーザーを認証するを参照してください。 - Elastic Load Balancing

設定 備考
有効なIDプロバイダ Cognito User Pool
コールバックURL https://(FQDN)/oauth2/idpresponse 多要素認証を利用するWebシステムのFQDNとします。/oauth2/idpresponse のパスは実在する必要はありません。
サインアウトURL https://(FQDN)/dummy 今回検証では利用しませんのでダミーのURLとします。
許可されている OAuth フロー Authorization code grant
許可されている OAuth スコープ openid

f:id:swx-miyagata:20220131170251p:plain

Cognito ユーザープールの画面で「アプリの統合」>「ドメイン名」をクリックします。 Cognito 側の URL に利用するドメインを設定します。本検証では Amazon のドメインをそのまま利用するので 「Amazon Cognito ドメイン」に任意の値を設定し、「使用可能かチェック」がパスすることを確認します。 独自ドメインを用いることも可能です。その場合は、ACM から証明書を取得します。

f:id:swx-miyagata:20220131170324p:plain

Cognito ユーザープールの画面で「アプリの統合」>「UIのカスタマイズ」をクリックします。 「カスタマイズするアプリクライアント」を、先ほど登録したアプリクライアントに設定します。 「ロゴ(オプション)」で、ログイン画面に表示される画像を自由に設定できます。他にも限定的ではありますがログイン画面UIのカスタマイズが可能です。

f:id:swx-miyagata:20220131170408p:plain

Cognito ユーザープールの画面で「アプリの統合」>「アプリクライアントの設定」をクリックします。先ほど設定を行った画面になりますが、画面下部の 「ホストされた UIを起動」がクリックできるようになっています。クリックして、自分が設定したドメイン名やロゴ等が反映されていることを確認します。

f:id:swx-miyagata:20220131170446p:plain

続けて、ユーザーの登録を行います。ID、パスワード、多要素認証のための情報(今回はSMSなので携帯電話番号)を登録します。 Cognito ユーザープールの画面で「全般設定」>「ユーザーとグループ」>「ユーザーの作成」をクリックします。

f:id:swx-miyagata:20220131170511p:plain

「ユーザーの作成」の画面になります。「ログインユーザーID(今回設定ではEメールアドレス)」、「パスワード」、「電話番号」、「Eメール」を登録します。 「検証済みにしますか?」は、今回の用途であればオン・オフどちらでも大丈夫です。

f:id:swx-miyagata:20220131170534p:plain

Cognito の設定は、ここまででいったん終了です。

AWS Certificate Manager の設定

ALB と Cognito を連携させる場合、ALB の仕様によりリスナーは HTTPS が必須です。そのため、SSLサーバー証明書が必要となります。 本BLOGの検証は、AWS Certificate Manager (ACM) を利用してSSLサーバー証明書を発行しました。私は お名前.com で取得した独自ドメインを使っております。 手順としては、弊社過去BLOGで紹介されていますので、本BLOGでは説明は割愛します。 blog.serverworks.co.jp

対象となるFQDNは、エンドユーザーが外部よりWebシステムへアクセスする際のURLとして利用します。

f:id:swx-miyagata:20220131170602p:plain

ALB の設定

AWSマネージメントコンソールの EC2 の画面より「ロードバランサーの作成」をクリックします。type は Application Load Balancer (ALB) とします。

f:id:swx-miyagata:20220131170645p:plain f:id:swx-miyagata:20220131170706p:plain

「Create Application Load Balancer」の画面となります。ALBの設定は本BLOGの趣旨からは外れるので詳細説明は割愛しますが、下記のように設定しています。

  • スキーム Internet-facing
  • Listener は HTTPS (port 443) として、バックエンドのWebシステムのサーバー(EC2)をターゲットグループに指定
  • SSLサーバー証明書は、先ほどACMで発行したものを選択

f:id:swx-miyagata:20220131170858p:plain f:id:swx-miyagata:20220131171124p:plain f:id:swx-miyagata:20220131171203p:plain

この後、ALB より払いだされたエンドポイントURLに対して、独自ドメインの CNAME レコードを設定しています。 まだ Cognito と連携する多要素認証の設定は行っていません。とりあえずインターネット外部から ALB 経由で、Webシステムがアクセスできるか確認します。 本BLOGではEC2上に導入した IIS の画面へのアクセスとしています。SSLサーバー証明書のFQDN違いエラー等が無いかもチェックします。

f:id:swx-miyagata:20220131171313p:plain

つづけて、ALB に Cognito 認証を設定します。作成した ALB を選択し、「リスナー」タブ >「HTTPS:443 のリスナーID」>「ルールの表示/編集」をクリックします。

f:id:swx-miyagata:20220131171424p:plain

ALB のルールの画面になります。上段タブの「編集(鉛筆マーク)」をクリックします。ルール一覧より「HTTPS:443 デフォルトアクション」の「編集(鉛筆マーク)」をクリックします。「ルールの編集」の画面で「THEN」列の「アクションの追加」をクリックすると、認証設定を入力する欄が表示されます。下記のように設定します。

パラメーター
認証 Amazon Cognito
Cognito ユーザープール 設定したユーザープール(候補に表示)
アプリクライアント 設定したアプリクライアント(候補に表示)

「詳細設定」「追加のリクエストパラメーター」はデフォルトとします。チェックボタンをクリックして設定を保存します。上段の「更新」ボタンをクリックします。「デフォルトルールは正常に更新されました。」が表示されることを確認します。

f:id:swx-miyagata:20220131171502p:plain f:id:swx-miyagata:20220131171622p:plain f:id:swx-miyagata:20220131171646p:plain

ALB の設定はここまでで終了です。多要素認証の動作確認に進みます。

多要素認証の動作確認

先ほど ALB の動作確認の時と同様に、インターネット外部から ALB 経由で Webシステムがアクセスします。設定が正しいと、Cognito のログイン画面へリダイレクトされる筈です。

実際やってみると、下記エラーとなってしまいました。 「An error was encountered with the requested page.」

f:id:swx-miyagata:20220131171700p:plain

原因はすぐにわかりました。Cognito 側で設定したコールバックURLの FQDN を間違えておりました。 訂正すると、無事 Cognito の認証画面へリダイレクトされるようになりました。

f:id:swx-miyagata:20220131171802p:plain

f:id:swx-miyagata:20220131171822p:plain

初回ログインではユーザー側でのパスワード変更が促されますので、パスワードを変更します。

f:id:swx-miyagata:20220131171844p:plain

SMS で携帯電話にワンタイムパスワードが届くので入力します。

f:id:swx-miyagata:20220131171903p:plain

多要素認証が成功すると、Webシステムにアクセスできるようになります。本BLOGではIISデフォルトページとなります。 これで一連設定、動作確認は完了です。

f:id:swx-miyagata:20220131172002p:plain

課題点

本BLOGの表題通り、AWSの機能でお手軽に多要素認証Webシステムを構築することができました。 ただし、この構成には2つほど課題があると感じました。

サインアウト機能が無い

ALBの初回アクセス時に Cognito の認証画面へリダイレクトしているだけなので、サインアウトする機能や画面が存在しません。AWSマニュアルにサインアウトの実装方法は紹介されていますが、もともと存在するWebシステム側で細工は必要のため、ユーザー側で多少なりとも実装が必要です。

当社先輩が過去BLOGでこの点を検証しておりますので、ご参照ください。 blog.serverworks.co.jp

Cognito の認証ログが記録されない

Cognito の認証ログは、CloudTrail に記録されることになっていますが、今回のように AWSが最初から用意しているログイン画面を用いる場合(Hosted UI)、CloudTrail にログが 含まれないとマニュアルに記載があります。

AWS CloudTrail を使用した Amazon Cognito API コールのロギング - Amazon Cognito

注釈 ホストされた UI とフェデレーションコールは、現在 CloudTrail に含まれていません。

しっかり認証ログを残したい場合、ユーザーで Cognito API を用いたログイン画面を実装するしか今のところは方法は無さそうです。本BLOGの趣旨である「お手軽」実装ではなくなってしまいますね。 元のWebシステム側で同様ログが実装されていないかご確認ください。

携帯番号へSMSにてワンタイムパスワードを送る点に着目すると、Amazon SNS 側でログを有効にすると 「いつ」、「どの電話番号」へワンタイムパスワードを送ったのかをログに残すことができましたのでご紹介します。

「Simple Notification Service(SNS)」>「テキストメッセージング(SMS)」>「テキストメッセージングの優先設定」>「編集」とクリックして進みます。 「テキストメッセージングの優先設定の編集」の画面が表示されます。「配信ステータスのログ記録 - オプション」セクションで「新しいサービスロールの作成」をクリックします。自動的に CloudWatch Logs へログを書き出すためのIAMロールが作成、割り当てされます。

f:id:swx-miyagata:20220131172119p:plain

下記の画面のようなログが CloudWatch Logs へ記録されます。電話番号へのメッセージ送信がわかれば、誰がIDパスワード認証を成功しかかは判別することができます。

f:id:swx-miyagata:20220131172206p:plain

まとめ

本検証で Amazon Cognito を用いることで、お手軽に多要素認証を用いてのWebシステム公開が行えることが確認できました。クラウドのメリットとして、使いたい時に使った分だけの課金システムがあります。

  • 外出先から業務を行う少数メンバーのみ利用
  • 短期間の在宅勤務時・出張時のみ利用

こういったスモールスタートでの開始に向いていると思われます。また、AWS では AWS Shield Standard の機能が無料で自動有効化されており、DDoSなどの攻撃対策が実装されている点も心強いです。 本BLOGをご覧なっていただいた方の参考になれば幸いです。

宮形純平(執筆記事の一覧)

クラウドインテグレーション部 技術1課

好きなお酒は缶チューハイと本格焼酎