2021-07-10

AWSやってみよう[03-セキュリティの根幹!面倒で心配なユーザ認証はAWS Cognito に任せちゃう!]

投稿者: KuRo

AWS Cognito

AWSやってみよう。
次の課題は、ユーザ認証回りのお話です。

WEBアプリケーションを制作する上で、最も面倒かつ心配な課題。ユーザ認証。
様々なフレームワークが利用できる今日の開発環境とはいえ、セキュリティの根幹となる機能なので心配の種です。

もちろん、完璧なものなんてないんですが、SaaSで作ればセキュリティ面のアップデートをメジャーなサービス(AWSなど)であれば、安全性や将来性もばっちり!

そもそも、本来の機能に力を入れるべきであって、ユーザ認証に頭を悩ませるなんて、本末転倒です。

では、さっそく環境整備していきましょう。

今回やることはこれです。

AWSでWebサービスを作る【目標】
  • メールサーバを立てる
  • 自前のドメインを設定する
  • ユーザID環境を作る      👈
  • ウェブサイト環境を作る
  • APIを作る
  • 他サイト連携を作る
  • DB環境を作る
  • 負荷分散環境を作る
  • ステージング環境を作る
  • DevOps環境を作る

AWS Cognito 概要

AWS Cognito 機能概要

AWS が提供するサービスで、ユーザ管理、ユーザ認証の機能を提供してくれます。

利用可能プラットフォーム ウェブアプリ、モバイルアプリ、Unity、Kindle Fire、Javascript など各プラットフォーム向けSDKが利用可能
主な機能 サインアップ、認証、SAML、OpenID Connect、ソーシャルIDプロバイダーのサポート
対応するIDプロバイダ Amazon、Facebook、TwitterDigits、Google など
SMS多要素認証 対応(1回のSMSメッセージあたり、0.07ドル程度の従量課金)
料金 同期オペレーション1万回につき0.15 USD
同期ストア 1GB につき、毎月 0.15 USD
同期オペレーションとは?
無料条件 月間アクティブユーザ(MAU:認証や登録変更などのアクションがあったユーザ数) 50,000 まで無料(無期限)

AWS Cognito 用語

大きく分けて、ユーザープールと、IDプール(フェデレーディッドアイデンティティ)の2つの機能が提供されます。

ユーザープール

まさにユーザー情報を格納する入れ物です。
SDKを利用してサインアップ、サインインするなら、ユーザープールだけ利用すればOKです。

これは、Cognitoでは新しい機能になります。
今回の記事は主にこれを作ります。

Google や facebook による認証は後で作るとして、単純にEメールアドレスを登録、検証したサインアップ機構と、サインイン機構をこれで整備します。

IDプール(フェデレーディッドアイデンティティ)

これは、Cognitoでは古参の機能です。

そもそも、別のユーザー管理プラットフォーム(Google、Facebookなど)の認証機能で認証された状態の人を、AWSの機能(S3とかLambdaとか)を利用する上で必要となる認可(アクセス権と考えてよい)と紐づける機能です。

要は、AWSの認証と、ユーザー管理プラットフォームとをつないでくれる機能です。
Cognitoユーザープールも「ユーザー管理プラットフォーム」のうちの一つとなります。

AWS Cognito 操作記録

ユーザプールの作成

ユーザプールとは、ユーザ情報を格納する場所だと思っていいと思います。

AWS Cognito ホーム – [ユーザープールの管理] をクリックします。

プール名入力

プール名を決めて入力します。
半角英数記号、空白のみ対応。

デフォルトで楽しようと思ったんですが、後から変更できない項目もあるので、[ステップに従って設定する] をクリックします。

サインインの方法を設定

サインインのID部分を、ユーザ名にするのか、Eメールや電話番号にするのかを決めます。
全部あり、もイケます。
ユーザー名にメールアドレスを使うのでもいいですが、Google認証やFacebook認証などのIDプロバイダを利用する場合、IDプロバイダから提供される任意のIDが採用されます。
同じメールアドレスで2アカウント作れると都合悪いときは「検証済みのEメールアドレスでのサインインも許可」にすれば、Eメールアドレスがユニークになりますね。

ユーザプロファイルの情報を決める

👆と同じ画面、少し下にスクロールして、ユーザに紐づけて管理する情報を決めます。
あらかじめ用意されている情報のほか、カスタム属性も追加できます。

ただし、外部ID連携を考えているなら、外部サービスに存在しない情報があったりすると厄介なので、あまりたくさん設定しないほうが良いと思います。

設定したら「次のステップ」をクリック

パスワード強度・サインアップ・一時パスワードなど

パスワードの強度を設定します。
WEBアプリなので、ユーザが自身でサインアップできるようにしたほうがいいですね。(手動管理なら管理者のみ作成許可かな)
一時パスワードの有効期間の設定もします。

多要素認証・パスワード忘れの設定

SMSによる多要素認証は都度課金ですので、ご利用は計画的に。
とりあえず、SMSはオフ。アカウント回復はEメールかな。
次のステップをクリック。

Cognito から送信するEメールの設定

認証周りでCognitoから送るEメールの設定をします。
自前のドメインのEメールアドレスから送信する場合は、Amazon SES の設定が必要です。

これは後でもできます。

前回の記事でAmazon SESを構築済み、かつサンドボックスを解除済みなら、SESリージョンやARN(SESを設定したら払い出されるもので、どのSESを使うか?的なヤツ)などを設定。
SESに設定済みのEメールアドレスを「FROM Eメールアドレス」「REPLY-TO Eメールアドレス」に設定し、「はい – Amazon SES を使用」を選択すればOK

ひとまず、Cognitoのメールアドレスとかで動作確認するなら、送信元Eメールアドレスを「FROM Eメールアドレス」「REPLY-TO Eメールアドレス」も空
「いいえ – Cognito を使用(デフォルト)」を選択します。

KuRo
KuRo
SESを使わない場合のメール送信元は「 no-reply@verificationemail.com 」のようですね。
これじゃイヤですよね。
ダマってSES設定しましょう。

メッセージのカスタマイズ

👆と同じ画面でちょっと下にスクロールして・・・・
Eメールの送達をどうやって確認するか設定します。

サインアップはPCだけど、メールはモバイルなんだよね。みたいな人もサポートしたいので、コードにするとよいですね。

Cognito のEメール検証はコードがオススメ
リンク にすれば、利用者はEメール添付のURLをクリックすればいいだけなので、そっちのほうが便利ですが・・・・
リンクの場合は「Cognitoに独自ドメインを設定しないと、アクティベートはできますが、Cognitoが用意する固定のページに飛ばす」だけです。
これじゃ、プロダクトの画面を出せないので、これじゃない感あります。

Cognitoに独自ドメインを設定するのは少しクセがあります。
面倒なので私はコードにしました。

KuRo
KuRo
私の場合、メッセージを日本語で色々書いてみたところ、最後の「プールの作成」ボタン押下時にエラーが表示されました。
空行とかも影響がありそう。
エラーの条件を特定するには至らなかったのですが、簡素なメッセージにしたら作成できました。

プールの作成以降、設定変更ではうまく設定できたりもします。
後でわかったら追記します。

一時パスワードのお知らせメールのカスタマイズ

👆と同じ画面でちょっと下にスクロールして・・・・
サインアップ時に発行されるEメールの文面を設定します。

これも後から修正可能です。

KuRo
KuRo
ここでもメッセージやプレースホルダー周りでのエラーに見舞われました。
空行をなくしたら通りました。

プールの作成以降、設定変更ではうまく設定できたりもします。

設定して次のステップをクリック

ユーザープールにタグをつける

いっぱいになったら考えよう。
次のステップをクリック。

ユーザーのデバイスを記憶するか決める

どんな利用方法があるんだろう?
そんなに情報いらないので いいえ
次のステップをクリック。

ユーザープールを利用するアプリを設定

後からでも設定可能ですから、いったんスキップでも問題ないです。
このユーザープールを利用するアプリケーションのIDを発行するところです。
IDには、ユーザープールの各値に対する読み書き権限を付けたりできます。

認証アプリにはRW、本人以外からも閲覧可能な機能にはRのみなど、アプリケーションレベルで権限分けしたりするのに利用できます。

認証周りの操作をトリガーする Lambda を設定

こりゃ便利そう。
Cognitoの動作をトリガーに、Lambda が動作できる。
でも、ここに設定すると、つながりを見失いそうな気もする。
後からでも設定できるので、いったん次のステップをクリック。

設定内容の確認をして「プールの作成」

最後におなじみの、設定内容の確認画面が表示されます。
メールの送信に Amazon SES を利用していないと赤文字表示されます。
後で設定できると信じてます。
「プールの作成」をクリック。

いったんプールは作成されました。

動作を見てみる

では、どんな動作をしてくれるのか確認してみましょう。

左上の「ユーザープール」をクリックすると、作成した名称が表示されます。
こいつをクリック。

ユーザーを手動で作成

左ペインメニュー [全体設定]-[ユーザーとグループ]をクリック。
[ユーザーの作成]をクリック。

適当にユーザー情報を設定してみましょう。
動作を見たいので、招待Eメールを送信。電話番号はなし。Eメールは検証済みチェックを外して作成してみます。

すると、設定したメッセージがEメールで届きます。

Cognitoの標準メールでは、送信元は「 no-reply@verificationemail.com 」のようですね。

プログラムから認証する

JavaScript ベースのアプリから呼び出しができます。
ブラウザベースのJSでも、Node.js(サーバサイドJS)でも動作するライブラリが提供されています。
[npm]amazon-cognito-identity-js
[git]amazon-cognito-identity-sdk-for-javascript

AWSのハンズオンでも一応簡単に紹介されています。(ハンズオンだけやっても、JavaScriptベースの認証をマスターできるほど理解はできません)
[AWS ハンズオン]build-serverless-web-app-lambda-apigateway-s3-dynamodb-cognito
上記のハンズオンで利用されているサンプルアプリのJSを眺めるだけで、だいたいの使い方は把握できると思います。

AWSから提供されるUIを使えば、画面作る必要もない

以下の条件を満たすと、Cognito が提供してくれる認証UIで一通りの機能を使えます。

Cognito が用意してくれるUIを使える条件
  • Cognitoにドメインが設定されていること(独自でもCognitoのサブでもOK)
  • アプリクライアントの設定(OAuth 2.0 スコープに email を含むこと)が完了していること

こんな画面

一応、ロゴを追加したり、CSSを調整することはできるのですが、文字を修正したり、エラーメッセージを変更するなどはできません。
テスト用とか、社内用なら耐えられるかな。

まとめ

Amazon Cognito を利用すると、サインアップ、サインイン、サインアウト、パスワードリマインドなどの環境をサクッと作れることがわかりました。
こいつから取得できるトークンを利用して、独自アプリでセッション管理するもよし、AWS の IAM を利用して、AWSのサービスの認可を与えるもよし。

一応UIまで用意してくれてはいるけど、本番用に耐えられるものではないです。

AWS の API Gateway をバックエンドとして開発する案件ならば、Cognitoを利用するのが良さそうです。