Amazon AlexaのAccount Linkingを使ってAmazon EchoからTwitterに書き込ませてみる

2017.04.05

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、せーのです。今日はAlexaを使って外部システムと連携してみよう、というお話です。

Account Linking

AlexaのCustom Skillは基本、そのSkillを使用可、とした人は誰でも使えるようになっています。しかしSkillの中には外部のシステムと連携してサービスを提供する際に認可が必要な場合が出てきます。
例えばタクシーを呼ぶSkillを作ろうとします。音声にてタクシーを呼ぶ、というケースを考えた場合、一番シンプルなのは「Alexa, タクシーを呼んで」と言えばタクシーが来る、という形です。そのためにはそのタクシー会社のシステムと連携して住所や名前等を自動的にDBから引っ張ってくる仕様にしないと「Alexa, ◯◯町◯番地◯◯マンションの前にせーの宛てのタクシーを一台呼んで。クレジットカード番号は、、、」という音声コマンドになってしまいます。
更に音声コマンドで毎回IDとパスワードを叫ばなくても良いようにするには、Skillを使用可にする段階でIDとパスワードを入力して、その後は毎回そのシステムを使うことを許可された状態にしておくのがスマートです。Alexaでこれを実現する機能が「Account Linking」です。Account Linkingは特にスマートホームを作るためのSkillであるSmart Home Skill APIを使う場合は必須となります。

ちなみにここで「認証」と「認可」の違いを押さえておきましょう。「認証」は「その人が◯◯さんである、ということを認める処理」で「認可」とは「XXサービスを使うことを認める処理」の事を言います。例えば「社員証をドアの前にかざすとドアの鍵が開く」というシステムの場合、「社員証を発行する」というのが認証、「ドアの鍵が開くシステム」が認可となります。社員証を発行するにはその人が社員である事を確認してから手続きが行われますが、ドアの鍵は誰かの社員証をかざせば、かざした人がその社員じゃなくても開きます。

Oauth2の仕組みを使う

Account LinkingはOAuth2.0でもWeb系で使いやすい仕組みである「Authentiation code grant」と「Implicit grant」という2種類の認可タイプに対応しています。
Authentication code grantはクライアントに対して「Client ID」と「Client Secret」という情報を発行し、その情報を持っているクライアントのみに認可を与える形で、Implicit grantはその簡易版のような位置づけとしてClient Secret無しで認可を与えます。Custom Skillでは両方の認可タイプが使えますが、Smart Home SkillではAuthentication code grantのみが使えます。

Oauth2.0ではAuthentication URL(認証URL)にstate, client_id, response_type, scope, redirect_uriをパラメータとして含めて渡しますが、Alexaの場合それぞれこのような位置づけになります。

名前 役割
state Alexaと認可サーバのセッション維持の為の乱数
client_id Alexa側を表すID
response_type Authentication code grant=>CODE / Implicit grant=>TOKEN
scope 認可サーバに認可させる範囲(ユーザ情報は渡すが決済情報は触らせない、等)
redirect_uri 認可後のリダイレクト先。Alexaの場合固定されている。

Twitterを使ってみる

さて、ここまで認可サーバの仕組みとAlexaをクライアントとした場合での認可システムの扱い方をご説明してきました。

account_linking14

しかし「認可サーバ」を構築するのは簡単ではありません。そこで既存のOAuthに対応しているプラットフォームを使うことを考えてみます。OAuthと言えばTwitterやFacebookがOauthに対応していることで有名です。よく「Facebookでログインする」というボタンを見かけると思いますが、あれはFacebookがそのアプリに対してFacebookにあるユーザ情報を使用したり、Facebookのタイムラインに投稿したりすることを「認可」している形になります。
今回はTwitterの認可システムを使ってオリジナルのシステムとAlexaのシステムを連携させるソリューションを作ってみましょう。TwitterはOAuth1.0方式になるので、間に1サーバ挟んでトンネリングさせる形になります。

account_linking15

やってみた

それではやってみましょう。今回はサンプルにある[Airport Info(各空港の遅延、欠航状況を調べてTweetするスキル)]を作っていきます。

まずはトンネル用のサーバを作ります。といってもAlexaのDeveloperサイトtwitter API用のサンプルへのリンクがあるのでここから落としてきてbundleするだけです。Ruby2.3とgemのbundleが必要なのでインストールしておきましょう。その他openSSL、GCC、gcc-c++をインストールします。無料のテスト用SSL証明書や余っている証明書を使用してSSLにて通信出来るようにしておきましょう。https://<ドメイン名>/appで下記の画面が出ればOKです。

account_linking10

次に同じサンプルから/skill以下をLambdaにアップロードします。package.jsonがあるのでそのままnpm installしてnode_modulesを作成し、各jsファイルとnode_modulesを合わせてzipで固め、それをLambdaにアップロードします。詳しくはこちらを御覧ください。

サーバが出来たらTwitterと結びます。TwitterのAppsページを開き、新規にアプリを作成します。

account_linking2

Websiteの所に[/app], Callbackの所に[/oauth/callback]をセットし、フル権限でアプリを作成します。

account_linking11

出来上がったclient_idとclient_secretをコピーしておきます。

最後にCustom Skill Setの作成です。基本的な作成方法はこちらを御覧ください。いつもと違う部分は[Configuration]の時にAccount Linkingを[Yes]にすることです。そうすると下部にAccount Linkingに必要な認可サーバの設定部分が表示されます。

account_linking12

Authorization URLの部分には

https://<ドメイン>/oauth/request_token?vendor_id=<下のRedirect URLsのvendorIdからコピー>&consumer_key=<Twitterのclient_id>&consumer_secret=<Twitterのclient_secret>

のようにして入力します。

[Domain List]には上記のAuthorization URLで設定しているドメイン以外のドメインを使用する場合に設定します。今回で言えばTwitter APIにアクセスしますのでそのドメインを入れておきます。通常はログインページの画像等を別のCDNなどから引いてくる場合にここに書き加えておきます。また今回はテストということでそんなにセキュリティの高くないImplicit Grantを使います。

あとは通常通りUtterance, Slot, Intent Schemaを埋めていきます。これも上記のサンプルコードの[/Skill/Resource]の中に入っているのでマルっとコピペしてもらえれば動きます。

account_linking13

Custom Skillを作り終えたらテストしてみましょう。AlexaのポータルサイトよりSkillを開き、右上にある「Your Skill」を開くと先程作ったCustom Skillが表示されています。

account_linking6

Account Linkingが必要な場合はこのようなマークが出ています。開くと[Link Account]というボタンが出てきます。

account_linking7

このLink AccountをクリックするとAccount Linkingに設定されているAuthorization URLに向けてrequestが飛びます。

account_linking8

Twitter APIからの認可が下りたらSkillとリンクされたことが表示されます。

account_linking9

これでAccount Linkは成功です。テストしてみます。ハーツフィールド・ジャクソン・アトランタ国際空港(空港コードATL)の様子をツイートして、と頼むとAlexaを通してツイートされ、返事が返ってきます。

Account Link Sample from Tsuyoshi Seino on Vimeo.

"Ask airport info to tweet flight status for ATL."

"I've posted the status to your timeline."

テスト成功です。

まとめ

いかがでしたでしょうか。認可サーバとしてはCognitoも使えますので、単純に「ログインできる人だけが使えるSkill」ならばCognitoのUser Poolで可能となります。OAuth2.0の仕組みは慣れるまでは結構骨の折れる作業ですので、じっくり取り組みながらお試し下さい。

参考リンク