初心者向け: API GatewayのAuthorizerを使ったLambdaとの認証情報連携
はじめに
JWTを用いてログインしたユーザーに紐づく情報をLambdaから返す、というよくある構成をPyJWTなどのデコードライブラリを使わずに実装します。
本記事はAWS側の実装までになります。
JWTとは何か?
JWT(JSON Web Token)はJSON形式のトークンで、情報を安全にやり取りするために使用されます。トークン内には改ざんを検知するための署名が含まれており、JWTを使用することでクライアントが正当なユーザーであることを確認することができます。
sub値をやりとりするのは危険! 7payの事例から学ぶ教訓
ユーザー情報を連携する際、署名を含むJWTを使わずにsub値(ユーザーを一意に識別する値)を使うことは大変危険です。過去に7payでは、署名を含まずに連携する仕組みだったがために、攻撃者によるなりすましログインを許してしまいました。
7pay外部ID連携の「脆弱性」の構造[1]
連携方法
Cognito→Lambda→API Gatewayの順で説明します。
ステップ1: Cognitoでユーザープールを作成
最初のステップでは、認証機能を提供するCognitoの設定方法を説明します。Cognitoでは、認証に関わる設定を詳細に選択できますが、本記事の論点ではないため基本デフォルトのままとします。
まずは、コンソールでCognitoを検索します。
「ユーザープールを作成」をクリック
サインインに使用する属性として「Eメール」を選択
パスワードポリシーはデフォルトで、多要素認証は「MFAなし」を選択
Eメールプロバイダは「CognitoでEメールを送信」を選択
任意のユーザープール名を入力。ここでは"myUserPool"と入力します。
任意のアプリケーションクライアント名を入力。ここでは"myAppClient"と入力します。
これでCognitoの設定は完了です。
ステップ2: Lambdaで関数を作成
次にLambdaでユーザーIDを示すsub値を取得する方法を説明します。
Lambdaの画面から「関数を作成」をクリック
任意の関数名を入力します。ここでは"myFunction"と入力します。
また、ランタイムはPythonを選択します。
以下のコードを実装し、"Deploy"をクリック
import json
def lambda_handler(event, context):
user_id = ""
if "requestContext" in event and "authorizer" in event["requestContext"]:
user_id = event["requestContext"]["authorizer"]["claims"]["sub"]
#user_idを使った何らかの処理
return {
'statusCode': 200,
'body': json.dumps('リクエストに成功しました')
}
else:
return {
'statusCode': 400,
'body': json.dumps('リクエストに失敗しました')
}
sub値は以下の部分で取得しています。
if "requestContext" in event and "authorizer" in event["requestContext"]:
user_id = event["requestContext"]["authorizer"]["claims"]["sub"]
こちらは、次章で説明するAPI Gatewayのオーソライザーで、リクエスト内に含まれるJWTの検証が成功した場合に取得できます。
このsub値を用いてユーザーに特定の権限を付与したり、データベースと連携したりすることができます。
これでLambda関数の作成は完了です。
ステップ3: API GatewayでAPIを作成しオーソライザーを設定
API Gatewayには、リクエストを認証し、認証されたユーザーにアクセスを許可するオーソライザーの機能が備わっています。この機能を利用して、JWTを検証します。以下のステップで設定を行います。
API Gatewayの画面で「APIを作成」をクリック
REST APIの「構築」をクリック
任意のAPI名を入力。ここでは"My API"と入力します。
次にオーソライザーを作成します。
左の「オーソライザー」から、「新しいオーソライザーを作成」をクリック
任意の名前を入力。ここでは"myAuthorizer"と入力します。
タイプは「Cognito」を選択し、Cognitoユーザープールは先ほど作成したものを指定します。
次にAPIのメソッドを作成します。
「アクション」から「メソッドの作成」をクリックし、GETメソッドを作成する。
GETのセットアップをします。
統合タイプは「Lambda」で、Lambdaプロキシ統合の使用にチェックを入れ、Lambda関数は先ほど作成したものを指定します。
最後にAPIにオーソライザーを設定します。
まず「メソッドリクエスト」をクリック
認可を先ほど作成したオーソライザーを指定します。
メソッドリクエストの認可が変更されていることを確認し、「アクション」から「APIのデプロイ」をクリック。ステージ名は任意で入力してください。ここでは"dev"とします。
URLが払い出されました。
まとめ
本記事では、認証機能の利用に必要なCognitoの設定と、API GatewayでJWTを検証する環境の構築及び、Lambdaでのsub値の取得方法を説明しました。
次回の記事では今回実装した環境を使って、Unityでサインアップ・サインイン機能を実装します。
Discussion