Edited at

javascriptでCognitoユーザプール認証

More than 1 year has passed since last update.

javascriptからCognitoのユーザプールで認証する方法を確認しました。

Amazon API GatewayのオーソライザーとしてCognito認証を指定することができますが、API Gatewayにアクセスする際にはCognito認証で取得したIDトークンが必要となります。

今回はIDトークンの取得とAPIへの与え方の確認になります。(qiita初投稿です)


0. 今回利用するサービスやモジュールたち


  1. Cognito (ユーザプール)

  2. node.js (javascript runtime)

  3. amazon-cognito-identity-js (Cognito javascript SDK)

  4. Axios (XHR library)


1. Cognito (ユーザプール) の設定

今回はユーザ・パスワードで認証させるだけなので、シンプルな構成でユーザプールを作成します。

ユーザプールIDとアプリクライアントIDはCognito認証時のパラメータとして必要となります。


  1. ユーザプールを作成していきます。

    userpool_1.png



  2. アプリクライアントの追加は実行しておきます。

    userpool_2.png


    userpool_3.png



  3. アプリクライアントの追加が完了したらユーザプールを作成します。

    userpool_4.png


完了したらCognito認証で利用するユーザも作成しておきましょう。

userpool_5.png

またユーザプールIDとアプリクライアントIDも確認しておきます。

(それぞれユーザプールの全般設定、アプリの統合>アプリクライアントの設定で確認します。)


2. Node.jsの設定

詳細は検索するなり参考サイトを確認ください。

MacOS(nodebrew)の場合は以下となります。

vi ~/.bash_profile

export PATH=$HOME/.nodebrew/current/bin:$PATH #この行を追記

brew install nodebrew
nodebrew install v8.10.0
nodebrew use v8.10.0

node.jsはDocker公式イメージが配布されているので、Dockerコンテナを使う手もありと思います。

docker pull node

docker run -it --name node node /bin/bash
...Dockerコンテナ内でセットアップ...。

以下のjavascriptライブラリを使うのでnode実行環境にインストールしておきます。(global installの方が良い?その場合はnpm install -g)

npm install --save amazon-cognito-identity-js

npm install --save axios

npm install --save node-fetch

以下のjavascriptを実行する際に必要となります。


3. Cognito認証するスクリプト実装

ユーザプール情報や認証データ情報を格納したオブジェクトをもとにCognitoUserオブジェクトを作成。

authenticateUser関数を実行し認証に成功すると、コールバック(onSuccess)に指定した関数が呼ばれます。(認証処理に失敗するとonFailureがコールされます)

コールバック関数内でAPIコールを行う処理を実装していますが、もっと良い方法があるかもしれません。

初回ログイン時はパスワード変更が必要となりますので(newPasswordRequiredがコールバックされる)、暫定で同一パスワードを設定します。

またnode.jsからスクリプトを直接実行する場合、ライブラリ群はCommonJS Modulesの形式でインポート(require)する必要があるようです。(SPAフレームワークの場合はES Modules形式も良いもよう)


testauth.js

global.fetch = require('node-fetch')

const AmazonCognitoIdentity = require('amazon-cognito-identity-js');
const axios = require('axios');
const config = require('./config')

login = function () {
let poolData = {
UserPoolId: config.UserPoolId,
ClientId: config.ClientId
};
let userData = {
Username: config.Username,
Pool: new AmazonCognitoIdentity.CognitoUserPool(poolData)
};
let cognitoUser = new AmazonCognitoIdentity.CognitoUser(userData);

let authenticationData = {
Username: config.Username,
Password: config.Password
};
let authenticationDetails = new AmazonCognitoIdentity.AuthenticationDetails(authenticationData);

cognitoUser.authenticateUser(authenticationDetails, {
onSuccess: function (result) {
let idToken = result.getIdToken().getJwtToken(); //Cognito認証で取得したIDトークン。 API gatewayへのアクセスに必要となる。
get(idToken); //IDトークンを指定してHTTPリクエスト(GET)を実行!
},
onFailure: function (err) {
console.log(err);
},
newPasswordRequired: function (userAttributes, requiredAttributes) {
cognitoUser.completeNewPasswordChallenge(config.Password, {}, this);
}
});
}


続いてHTTPアクセス用の関数の処理を追加します。

XHRライブラリはAxiosを使いました。

axios.get関数にて指定したURLへGetリクエストを送信できます。

Cognito認証を有効にしたAmazon API Gatewayにアクセスする場合、AuthorizationヘッダーにIDトークンを指定します。


testauth.js

get = function (idToken) {

let headers = { headers: { 'Authorization': idToken } };

axios.get(config.apiGatewayUrl, headers).then(
function (res) {
console.log(res.data);
}
).catch(
function (err) {
console.log(err);
}
);
};

login(); //おっと、こいつがないとAPIコールされんかったです。


ユーザプール情報や認証情報は外部スクリプトに記載しておき、処理時にrequireでインポートします。


config.js

module.exports =  {

apiGatewayUrl: 'https://xxxxx.xxxx.amazonaws.com/yourapi',
UserPoolId: 'CognitoユーザプールID',
ClientId: 'CognitoユーザプールのクライアントアプリID',
Username: 'Cognito認証を利用するユーザのID',
Password: 'Cognito認証を利用するユーザのパスワード'
}


上記を用意したら、コマンドラインからのスクリプト実行にてAPIコールが可能です。

node testauth.js

APIコールのレスポンスがコンソールに出力されますが、スクリプトやAPI側に必要に応じて何らかの処理を実装します。



まとめ

javascriptからCognitoのユーザプールで認証し、その際に取得したIDトークンをHTTPヘッダーに含めAPIコールを行う処理を試してみました。次はAmazon API Gatewayの実装方法を確認していきたいと思います。

また誤り漏れや改善点があれば適宜修正していきたいと思います。(例によって説明不足のところもあるので・・・。)



参考サイト

Amazon-Web-Servicesを使ったサーバーレスアプリケーション開発ガイド(書籍)

DockerHub(node)

nodebrew

fetch is not defined #403

amazon-cognito-identity-js

axios