javascriptからCognitoのユーザプールで認証する方法を確認しました。
Amazon API GatewayのオーソライザーとしてCognito認証を指定することができますが、API Gatewayにアクセスする際にはCognito認証で取得したIDトークンが必要となります。
今回はIDトークンの取得とAPIへの与え方の確認になります。(qiita初投稿です)
###0. 今回利用するサービスやモジュールたち
- Cognito (ユーザプール)
- node.js (javascript runtime)
- amazon-cognito-identity-js (Cognito javascript SDK)
- Axios (XHR library)
###1. Cognito (ユーザプール) の設定
今回はユーザ・パスワードで認証させるだけなので、シンプルな構成でユーザプールを作成します。
ユーザプールIDとアプリクライアントIDはCognito認証時のパラメータとして必要となります。
- ユーザプールを作成していきます。
3. アプリクライアントの追加が完了したらユーザプールを作成します。
完了したらCognito認証で利用するユーザも作成しておきましょう。
またユーザプール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形式も良いもよう)
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トークンを指定します。
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でインポートします。
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