Cognito認証による任意ユーザのLexボットアクセス

渡辺です。

LexボットはAWS上のサービスとして構築されます。 すなわち、Lexボットにアクセスするには AWSリソースへのアクセス が必要です。 原則として、AWSリソースへアクセスするには 認証情報 が必要であり、何らかの方法でクライアントが認証しなければなりません。

最も簡単にクライアントから認証する方法は、IAMユーザのアクセスキーとシークレットキーを使う方法です。 勿論、LambdaやEC2上での利用ならばIAMロールの利用がベストです。 しかし、iOS、Android、公開されたウェブページ上のJavaScriptなどに アクセスキーを晒すのは危険 です。

このようなケースでは、Cognitoを利用して認証しましょう。

Cognitoとは?

Amazon Cognito とは、ウェブアプリケーションやモバイルアプリケーションの認証、許可、ユーザー管理をサポートするサービスです。 例えば、FacebookやTwitterなどのログインと組み合わせ、認証済みのユーザにAWSリソースへのアクセス許可を与えます。 Cognitoの持つユーザプールを利用すれば、AWS単体で認証サービスを利用することも可能です。

今回、「任意のユーザがLexボットを利用する」という要件であるため、Cognitoの「認証されていないID」を利用します。 「認証されていないID」では、ログイン(認証)をせずに、Cognitoからアクセス許可を得られます。

フェデレーテッドユーザーアイデンティティの作成

はじめに、Cognitoでフェデレーテッドユーザーアイデンティティを作成します。 Cognitoの画面を開き、適当なIDプール名(LexBot)を付けてフェデレーテッドユーザーアイデンティティを作成してください。 この時、「認証されていないIDに対し、アクセスを有効にする」にチェックを入れておきます。

次の画面では、Cognitoで認証が行われた時に許可するアクセス許可を設定します。 アクセス許可はIAMロールとして設定しますが、IAMロール自体は自動的に作成されるため、ロール名をメモしておきましょう。 今回関連するアクセス許可は、認証をしていない場合のIAMロールなので、「Cognito_LexBotUnauth_Role」です。

フェデレーテッドユーザーアイデンティティが作成できたならば、サンプルコードからプラットフォームでJavaScriptを選択し、AWS認証情報の取得にあるコードをコピーしておきます。

アクセス許可の追加

認証していないユーザでCognitoにアクセスは出来るようになりました。 しかし、まだLexにアクセス出来ません。 アプリケーションなどで例えれば、ログインは可能でも、なにも操作権限がない状態です。 IAMの画面を開き、認証をしていない場合のIAMロール(Cognito_LexBotUnauth_Role)にアクセス許可を追加しましょう。

インラインポリシーの追加を選択し、サービスでLexを指定したならば、PutTextPutContextのアクションにチェックを入れます。 PutTextはLexに対し文字情報を送信するアクションで、PutContextは音声などバイナリを送信するアクションです。 テキストのみであれば、PutTextだけでも良いでしょう。

インラインポリシーには適当な名前をつけて保存します。

注意したいのは、特に、 認証なしで利用できるロールに対し、強力なアクセス許可を与えない ことです。 Administrator権限などは言語道断ですが、Lexのフルアクセス許可を与えてしまうと、Lexボットを削除したり、Lexボットの挙動を変えることも可能です。

クライアントからの利用

以上で認証不要でLexクライアントが利用できる準備ができました。 先ほどのサンプルコードを元に、JavaScriptでクライアントの実装を行うことができます。

要点のみを抽出したコードは次のようになるでしょう。

AWS.config.region = 'us-east-1';
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
    IdentityPoolId: 'us-east-1:xxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxx',
});
var lex = new AWS.LexRuntime();
var postMessage = function(message) {
    var params = {
        botName: 'LexBot',
        botAlias: 'Prod',
        userId: 'anonymous',
        inputText: message
    };
    lex.postText(params, function(err, data) {
        if (err) {
            console.log(err, err.stack);
            return;
        }
        console.log(JSON.stringify(data));
    });
};

まとめ

クライアントからLexボットにアクセスするには、AWSリソースへのアクセス許可が必要です。 アクセス許可を得るには、Cognitoを利用します。 Cognitoでは認証なしで利用できるオプションがあるため、認証なしでアクセス許可を与えることができます。

ただし、与えるアクセス許可は最小限にしてください。 クライアントのコード(特にJavaScript)が公開されているならば、誰でもそのアクセス許可を得られるためです。

以上、良いチャットボットの作成を!