Amazon EchoからSlackに通知を出してみた(Cognito + API Gateway版)

前回前々回 とAlexaからSlackに通知できる仕組みを試してみましたが、Alexaから呼ばれるLambdaに接続先やメッセージを環境変数で設定する必要があり、ユーザ毎にできるようにしたくなってきました*1

今の仕組みでも、Alexaユーザーとシステムユーザーを関連付けることができます。そこから接続情報やメッセージを引っ張って来れればうまく行きそうです。

  • ユーザ毎に情報を保持するアプリ
  • Alexa SKill

の2本立てで行きたいと思います。

Serverlessの為にどんな構成にする?

  • ユーザ管理・認証
  • ログイン済みのユーザに紐付くデータ
    • API Gateway経由でhtmlを返したりAPIを叩いてデータにアクセスする

永続化は?

最初はユーザに紐付く情報をCognito Syncで考えていたのですが、各端末間のデータ同期に特化したサービスらしく、Lambda上でユーザに紐付く情報を取得するのは難しそうでした。なので、保存先はDynamoDBで行います。

イメージはこんな感じです。 f:id:nemuzuka:20180120150534p:plain

ユーザ毎に情報を保持するアプリ

API Gateway経由でリクエストを受け取り、レスポンスを返します。AlexaからKickされたLambdaがユーザに紐付く情報を取得するのもこのアプリ経由になります。設定画面は誰からもアクセスされると困るので、API Gateway 側でTokenの有効性をチェックします。

コード

Alexa Skill

AlexaからKickされたLambdaはAccess Tokenを元にユーザに紐付く情報を取得します(アカウントリンクを有効にします)。そして、その情報を元にSlackに通知を投げます。

コード

ちょっと気になる点

それぞれのGitHubリポジトリ上に構築手順をまとめましたので、気になる方はぜひ試してみてください。 実は、API GatewayのカスタムオーソライザーでCognitoのarnを直接設定できます。これでTokenの有効性チェックを自前で行う必要はないのですがID Tokenしか有効でないらしく、AlexaからKickされたLambdaにはAccessTokenしか渡ってこない為、自前でチェックしています。その辺ご存知の方がいらっしゃればご教示頂きたいです。

まとめ

現在、Alexaからユーザ固有の設定をリクエストパラメータ的に渡すのは難しいので、外部のシステムに保持させておき、Access Tokenを元に取得するという方法が実現できました。これでちょっとスマートスピーカーの使い道も広がるんじゃないかと思います。

*1:流石にユーザに声でメッセージやURLを伝えてもらうのは無理ゲーだと思いました