AWS API Gatewayチュートリアルの手順5
手順5 - IDフローにIDトークンを使用する
この最後の手順では以下を行います。
OpenIDのJSON Web Token(JWT)を渡して、サービスへIDを送る
トークンを検証する
プロファイル情報を抽出して、ペットの購入者を割り当てる
IDトークンを使用する
ユーザーに関する情報の処理や取得には、Lambda関数を使用することができます。たとえば、購入トランザクション中に、IDトークンで返されたプロファイルからユーザー名を取得したとします。その際に、JSON Web Token(JWT)であるID自体に埋め込まれたユーザーの情報も取得することができます。
JWTの使用する利点は、以下を行えることです。
JWTの真正性を検証する
呼び出しを行っているユーザーが認証されることを確実にする(改ざんの可能性があるプレーンテキストのパラメーターに依存しない)
その他にも、認可にJWTを使用して、Amazon API GatewayとのIAM統合を迂回することができます。認可にAPI Gatewayを使用すると、Lambda関数を呼び出す前にAPIの呼び出しを止められることに注意してください。
JWTに情報を追加する
JWTにユーザー情報を追加するには、いくつかの方法があります。以下の例では、ユーザーのメールアドレスをJWTに追加していますが、概念は他のユーザーのデータポイントについても同じです。
ルールを使用する
ユーザーのメールアドレスをJWTに追加する方法の1つが、ルールです。この方法は、値がユーザー認証用のJWTで常に利用可能なことを確実にしたい場合には適切です。
login.js
では、auth.signin
に渡されるパラメーターにこのスコープが指定されているのを確認できます。
$scope.login = function() {
var params = {
authParams: {
scope: 'openid email'
}
};
auth.signin(params, function(profile, token) {
...
}
}
Was this helpful?
JWTにはユーザーのプロファイル全体を含めることもできますが、JWTは通常すべての要求で渡されるため、必要なものだけを含めるようにします。
JWTトークンを検証する
AWS Lambdaコンソールは、ブラウザーコンソールでNode.jsコードを入力する際に、限られた数のノードモジュールにのみアクセスするため、IDトークンを処理するパッケージとして追加でモジュールをインクルードして、Lambda関数をアップロードする必要があります。
詳細については、「Node.jsを使って導入パッケージを作成する」と「導入パッケージをアップロードしてテストする」をご覧ください。
以下のシードプロジェクトには、更新されたAWS Lambda関数に必要なコードが含まれています。
<%= include('../../../_includes/_package', { org: 'auth0', repo: 'auth0-aws', path: 'examples/api-gateway/lambda' }) %>
シードプロジェクト内には、以下の2つのカスタムJavaScriptファイルがあります。
index.js
:メインコードが含まれています。auth0-variables
:更新する必要のあるコードが含まれています。
カスタムファイルに加えて、Node.jsに標準のpackage.json
ファイルがあります。
コードは、JWTから情報を抽出して、JWTを検証するために機能性を追加します。Auth0はデフォルトで対称キーを使用しますが、非対称キーの使用を選ぶこともできます(サードパーティがトークンを検証可能にする必要がある場合には、非対称キーを使用して、公開鍵だけを共有します)。
トークン検証の詳細については、「Auth0が対応しているIDプロトコル」をご覧ください。
秘密鍵でauth0-variables.js
を更新します。秘密鍵は、Auth0 Dashboardにある[Application(アプリケーション)]の[Settings(設定)]タブに表示されます。
var env={};
env.AUTH0_SECRET='{yourAuth0Secret}';
module.exports = env;
Was this helpful?
ファイルのあるディレクトリからnpm installを実行して、内容をZIP形式で圧縮し(index.js
は必ずZIPのルート)、Lambda関数のPurchasePet
が使えるようにアップロードします。これをテストすると、JWTがメッセージの本文にないため、認証が失敗します。
index.js
でロジックを確認します。60行目辺りのロジックではトークンが検証して解読され、購入ロジックで使われるID情報が含まれた、デコードされた情報が抽出されています。
if(event.authToken) {
jwt.verify(event.authToken, secret, function(err, decoded) {
if(err) {
console.log('failed jwt verify: ', err, 'auth: ', event.authToken);
context.done('authorization failure', null);
} else if(!decoded.email)
{
console.log('err, email missing in jwt', 'jwt: ', decoded);
context.done('authorization failure', null);
} else {
userEmail = decoded.email;
console.log('authorized, petId', petId, 'userEmail:', userEmail);
dynamo.getItem({TableName:"Pets", Key:{username:"default"}}, readcb);
}
});
} else {
console.log('invalid authorization token', event.authToken);
context.done('authorization failure', null);
}
...
Was this helpful?
プロファイル情報を抽出して購入者を割り当てる
最後の手順では、JWTをブラウザーのクライアントが使用するメソッドに渡します。
標準のメソッドにはAuthorization
ヘッダーがBearerトークンとして含まれており、このメソッドを使用するには、IAM認証を無効にして、認証にOpenIDのトークンだけを使用する必要があります(AWS Lambda関数に渡すイベントデータにAuthorizationヘッダーをマッピングすることも必要です)。
ところが、IAMを使用している場合、AWS API GatewayはAuthorization
ヘッダーにメッセージの署名を含んでいるため、このヘッダーにJWTを書き込むと認証が破壊されます。これは以下のいずれかの方法で対処します。
JWTのためにカスタムヘッダーを追加する
メッセージの本文にカスタムヘッダーを入れる
カスタムヘッダーの使用を選んだ場合には、pets/purchase
のPOSTメソッドの統合要求に何らかのマッピングを行う必要があります。
検証プロセスを続けるために、AWS Lambda関数へのPOSTの本文でJWTを渡します。これを行うには、以下のように、本文からuserName
を削除して、authToken
を追加することで、home.js
でbuyPet
メソッドを更新します。
function buyPet(user, id) {
var apigClient = getSecureApiClient();
var body = {
petId:id,
authToken: store.get('token')
};
apigClient.petsPurchasePost({}, body)
.then(function(response) {
console.log(response);
$scope.pets = response.data;
$scope.$apply();
}).catch(function (response) {
alert('buy pets failed');
showError(response);
});
}
Was this helpful?
S3のバケットにコードをアップロードして、ペットを購入しようとしてみてください。出力のメッセージに購入者のメールアドレスが表示されているはずです。
エラーがあった場合には、秘密鍵を正しく設定したことを確認してください。トークンのデコードの問題を確認する便利なツールの1つが、jwt.ioです。
Summary(概要)
このチュートリアルでは、以下について説明されています。
AWS Lamdba関数を用いたメソッドなど、AWS API Gatewayを使ってAPIを作成する
IAMロールを使ってAPIへのアクセスを保護する
APIへのアクセスをユーザーベースと結び付けて、SAML IDプロバイダーとIAMを統合する
ユーザーがデータベース接続か、ソーシャル接続かを基にして、異なるレベルのアクセスを提供する
Auth0を使ってロールの割り当てを強制する
JWTを使ってより細かな認証コンテキストを提供し、ID情報を適切なLambda関数に渡す