背景
AlexaのCognitoによるアカウントリンク後、Cognito(User Pool)が保持する属性情報を取得したかったのです。
こちらの記事を参考にさせていただいて、「あれ?できない?いやでも、これはIdentity Poolに関する話だから違うよな?User Poolならいけるよな?」というところからスタートです。
とりあえずマニュアル見る
ユーザーがアカウントをリンクすると、ユーザーのアクセストークン(accessToken)がスキルに送信されるすべてのリクエストに含まれるようになります。
アクセストークンは取得できるので、何とかなりそうです。
accessTokenをすべてのリクエストに含まれるapiAccessTokenと混同しないでください。apiAccessTokenは、デバイスアドレスAPIやプログレッシブ応答APIなどのAlexa Skills Kit APIで使用されます。
ふむふむ、なるほど。了解です。
で、実装例は?
const OrderCarIntentHandler = {
//...
handle(handlerInput){
// このインテントではユーザーのタクシー予約プロフィールと支払い情報を
// 取得するためにアクセストークンが必要です。
// アクセストークンはContextオブジェクトにあります。ハンドラーに渡される
// HandlerInputオブジェクトでリクエストに
// アクセスします。
var accessToken = handlerInput.requestEnvelope.context.System.user.accessToken;
// ...
}
};
ちゃうねん。そのトークンの利用方法知りたいねん。
トークンがリソースサーバーの有効なユーザーを表していることを確認します。
はい。
トークンが有効な場合、リクエストを正常に処理します。トークンを使い、必要に応じてリソースサーバーからデータにアクセスできます。
はい。
・・・え、これで終わり?
え、このトークンってCognitoのCredentialなの?これでAuthorizedなIAM Roleの権限取れるん?なんか違うような、、、
リソースサーバーって、Cognitoの「ホストされたUI」とかで定義されてるやつだっけ。
解答
素直にサポートの方に教えてもらいました。
// User Poolから情報を取得する
const domain = 'alexa-user-pool';
const url = 'https://' + domain + '.auth.ap-northeast-1.amazoncognito.com/oauth2/userInfo';
const accessToken = h.requestEnvelope.session.user.accessToken;
const options = {
uri: url,
method: "GET",
headers: { Authorization: 'Bearer ' + accessToken },
}
const id = JSON.parse(await rp(options)).profile;
あー!こういうこと!
認証周りに詳しい方なら一瞬でたどり着きそうな話でした。そうか、oauth2/userInfoのエンドポイントか、、、
よく調べたら、LINEとアカウントリンクした場合の実装に関する記事もありました。
OIDCとかOAuth2.0とか、完全に理解したとか言ってないでちゃんと勉強しないとダメな好例でした。
アカウントリンク設定時のClient Secretに与えるread権限次第で、User Pool内の任意の属性を取得できることも確認できました。
どなたかのお役に立ちましたら幸いです。