3連休にCognito vue/aws-amplifyを使って手軽に認証機能をハンズオン
はじめに
こんにちは、江口です。
前回は人事選考の自動化を作成するにあたり、認証基盤をFlask JWTでOAuth2を自作しました。
が、
認証認可の処理はAWS Cognitoに丸々載せ替えることもできます。
Cognitoに載せ換えることで、前回ほどの労力・工数はかなり削減されます。
ということで、今回はCognito + APIGatewayと時々aws-amplify(with vue)のハンズオンです。
また、今回はFacebookやTwitterなどのThirdPartyは取り扱いません。
目指す構成は以下です。
構成図
- Cognitoに認証を任せ、AccessTokenを取得する
- ※フロントはvue x aws-amplifyの構成です。
- 取得したAccessTokenをAuthorizationHeaderに付与し、APIGatewayをコールする
- APIGateway(lambda)では、tokenの検証と検証を通過すれば、バックに構える各APIにproxyする
- 各APIはクライアントにJSONを返す
- ※各APIはAPIGatewayからのリクエストのみを許可します。
認証はCognitoに任せ、取得したtokenをheaderに仕込んだまま、
APIGatewayもコールしますが、実質APIとしてJSONを返すのはバックに構えるAPIサーバになります。
これにより、Lambdaの処理の中で、URLパターンを見て「/hoge」ならこのAPIに、「/fuga」ならこのAPIに。と、処理を各APIに移譲できます。
認証は共通でCognitoを使うが、サービスは複数ぶら下がることができるという狙いです。
上記が最終形ですが、二回に分けて紹介しようと考えているため、
今回は以下の構成までをハンズオンします。
- Cognitoに認証を任せ、AccessTokenを取得する
- ※フロントはvue x aws-amplifyの構成です。今回はlocalhostです
- 取得したAccessTokenをAuthorizationHeaderに付与し、APIGateayをコールする
- APIGateway(lambda)では、tokenの検証と検証を通過すれば、クライアントにテスト用のJSONを返す
つまり、オリジナルのAPIへのproxy部分は今回は作りません。
あくまで、CognitoとAPIGatewayの連携に焦点を当てたサンプルを作成します。
用語について
今回触れていく用語について簡単に紹介します。
Cognito
認証・認可をサポートしてくれます。
今回は下記のUserPoolsとFederated Identitiesとセットで使います。
APIGateway
APIです。
今回はLambdaと連携してJSONを返します。
オーソライザと呼ばれる機能を使い、Cognitoで認証を通過したアクセスのみ、
APIへのアクセスを認可するようにしています。
認証に通過したユーザーはtokenを取得して持っているはずなので、tokenをAuthorizationHeaderにセットしてAPIにアクセスすることでAPIGatewayにアクセスできるようになります。
aws-amplify
Cognitoを簡単に利用できるようになるjsライブラリです。
これまではCognitoIdentity SDKとAWS SDKを組み合わせて使う必要がありましたが、
amplifyのみで完結できるようになりました。
▼Github
github.com
Try
Cognito - UserPool -
まずはCognitoのUserPool設定からやっていきます。
これがないと始まりません。
AWSマネージメントコンソールにsighnInし、「Cognito」を開き、
以下の「ユーザープールの管理」を押下します。
押下したら、新規でユーザープールを作成しますので、
「tutorial」と命名し、「デフォルトを確認する」を選択します。
デフォルト設定のプレビューが表示されます。
こちらはあとで編集できますので、とりあえず「プールの作成」を押下し、作成を完了します。
完了したらダッシュボードに遷移すると思いますので、
「アプリクライアント」の「アプリクライアントID」の値をコピーしておいてください。
「アプリクライアントの設定」のを押下し、以下になるようにチェックを入れます。
また、注意点として、「アプリクライアント」の「クライアントシークレットの生成」はチェックが外れていることを確認してください。
これだけで、まずは簡単に器ができました!!
最後にUserPoolを利用する側のクライアントの設定をちょろっといじります。
callback urlでerrorが出る場合は、一旦サンプルなので「http://localhost:9999/test.php」とでも入れておいてください。
ログイン成功後にaccess_tokenがハッシュ文字列として付与されたURLにリダイレクトされますが、今回は使いません。
「許可されているOAuthフロー」で「Implicit grant」を選択しましたが、
「Authorization code grant」との違いはこちらを参考にしてください。
ユーザープールのアプリクライアントの設定 - Amazon Cognito
今回は「Implicit grant」 = 「認証エンドポイントから直接AccessTokenを取得」する方法にしました。
Cognito - Federated Identities -
続いて、Identityを作成します。
ヘッダーに「ユーザープール | フェデレーティッドアイデンティティ」とメニューがあるので、「フェデレーティッドアイデンティティ」を押下します。
押下したら、こんな画面に移るので、IDプール名には適当なnameを入力し、
「認証プロバイダー」の「Cognito」タブ「ユーザープールID」に先ほど作成したUserPoolのIDを記入し、アプリクライアントIDに先ほどコピーしたIDを記入します。
記入したら、「プールの作成」を押下します。
※この時エラーが出ることがありますが、時間を置いてから押すことで無事に作成されました。なんでしょうかね。
これで完了です。
続いてIAMの設定画面に移りますので、デフォルトのまま、AUTHロールとUNAUTHロールを新規作成します。
これでIDプールの作成は完了です。
Cognitoの確認
Cognitoはログインページがデフォルトで用意されるので、試しに表示して見ます。
以下のようにURLを組み立ててアクセスしてみると...
"https://YOUR_DOMAIN/oauth2/authorize?response_type=token&client_id=[YOUR_CLIENT_ID]&redirect_uri=http://localhost:9999/test.php"
このようなデフォルトUIが表示されます。
実際にログインすると、AccessTokenが帰ります。
試しに、localhost:9999でphp -aでlocalServerを立ち上げて見ます。
# vi test.php
<?php
$str = $_SERVER["REQUEST_URI"];
preg_match('/#(.+)$/', $str, $res);
var_dump(parse_url($str));
中身は適当でいいです。
作成したらlocalhostを立ち上げます。
# php -S localhost:9999
立ち上げたら、先ほどのURLにアクセスして見ますと...
http://localhost:9999/test.php#id_token=eyJra...[省略]&access_token=....[省略]&expires_in=3600&token_type=Bearer
このような形でTokenが取得できるかと思います!!
APIGatewayの用意
認証基盤は用意できたので、続いてプロキシとしてのAPIGateWayを用意します。
ですが、今回はプロキシではなく、「Cognitoの認証を通過したTokenを持ったリクエスト時にのみ、JSONを200Statusで返す」まで作って見ます。
まず、こちらを参考に、以下のようなlambda関数を一つ作成してください。
・関数名「cognito-tutorial-lambda」
def lambda_handler(event, context):
return {
"statusCode": 200,
"body": 'Hello from Lambda!'
}
私はPythonが好きなのでpython36を選んでますが、ここは何でも構いません。
続いて、APIGatewayに遷移し、新し いAPIの作成で適当にテスト用のAPIを作成します。
「新しいAPI」で「APIの作成」を押下します。
以下のようにドロップダウンメニューから「リソースの作成」でtestディレクトリを作成します。
ディレクトリが作成できたら、「メソッドの作成」からGETメソッドを作成し、統合タイプを「Lambda関数」にし、先ほど作成したlambda関数名を入力して作成してください。
これでGETでJSONを取得するAPIが一つできました。
最後に/testを選択した状態でドロップダウンより「CORSの有効化」を行います。
CORSの設定として、今回は「Access-Control-Allow-Origin」ヘッダに「http://localhost:8080」を設定しました。
これで、あとで紹介するフロントでresponse bodyを受け取れるようになります。
(※ Access-Control-Allow-Originに指定されたドメイン以外からのリクエストだと、ブラウザがresponseを取得 しません。)
APIGatewayAPIにオーソライザーを新規追加する
しつこいですが、Cognitoで認証を通過したユーザーだけがAPIにアクセスできます。
それ以外のユーザーは401ないしは403となります。
ちゃっちゃかやっていきます。
先ほど作成したAPIのメニューから「オーソライザ」を選択し、「新しいオーソライザを作成」を押します。
上図のような設定になるように、作成すれば完了です。
オーソライザをAPIのアクセス制限に設定する
追加したオーソライザをAPIに当てていきます。
先ほど作成した「GET: /test」エンドポイントを選択し、「メソッドリクエスト」をクリックすると、以下のような設定画面に遷移します。
「認証」に先ほど追加したオーソライザを選択します。
画面キャプチャから漏れてしまいましたが、「HTTTPリクエストヘッダー」の開き、「Authorization」を追加、必須に指定します!
これで準備は完了です。