MFAのアクセストークンを検証する
スコープの確認に加えて、APIはアクセストークンを検証して次の操作を行う必要があります。- トークンの署名を検証します。これは、トークンの送信者が本人であることを確認し、メッセージが途中で変更されていないことを確認するために使用されます。
-
標準クレームを検証します。
クレーム 説明 expトークンの有効期限 issトークンの発行者 audトークンの意図された受信者
シナリオ:プッシュ通知による銀行取引
次のシナリオでは、アプリケーションがユーザー名とパスワードでユーザーを認証し、口座残高を要求します。口座残高情報を取得する前に、ユーザーはGuardianプッシュファクターで認証する必要があります。 銀行APIは、口座残高の表示(スコープview:balance)または資金の振替(スコープtransfer:funds)という2つの異なるレベルの承認を受け入れることができます。アプリケーションがAPIにユーザーの残高の取得を要求する場合、アクセストークンにはview:balanceスコープが含まれている必要があります。別の口座に送金するには、アクセストークンにtransfer:fundsスコープが含まれている必要があります。
ワークフロー
- ユーザーは、ユーザー名とパスワードの認証を使用してアプリケーションにログインします。標準ログインにより、このユーザーはAPIと対話して残高を取得できます。つまり、ユーザーが認証した後にアプリが受け取るアクセストークンには、
view:balanceスコープが含まれます。 - アプリケーションは、アクセストークンを資格情報として使用して、残高を取得する要求をAPIに送信します。
- APIはトークンを検証し、残高情報をアプリケーションに送信して、ユーザーがそれを表示できるようにします。
- ユーザーは、あるアカウントから別のアカウントに資金を移動したいと考えています。これは、
transfer:fundsスコープを必要とする高額トランザクションと見なされます。アプリケーションは同じアクセストークンを使用してAPIに要求を送信します。 - APIはトークンを検証し、トークンに必要な
transfer:fundsスコープがないため、アクセスを拒否します。 - アプリケーションはAuth0にリダイレクトします。そこで、高額スコープが要求されたため、アクションを使用してユーザーにMFAによる認証を要求します。ユーザーがMFAで正常に認証されると、正しいスコープを含む新しいアクセストークンが生成され、応答の一部としてアプリケーションに送信されます。
- アプリケーションは、新しいアクセストークンを使用して別の資金振替要求を送信します。このトークンには、今回は
transfer:fundsスコープが含まれています。 - APIはトークンを検証し、破棄して操作を続行します。
前提条件
このシナリオでは、ダッシュボードで次の項目を構成する必要があります。- シングルページWebアプリを登録します。
- データベース接続を作成します。
- APIを登録します。次の2つのスコープを作成します。
view:balanceとtransfer:funds. - プッシュ通知を使用するには、MFAを有効化します。
アクションを作成する
transfer:fundsスコープが要求されたときに、ユーザーにMFAによる認証を要求するアクションを作成します。[Dashbord]>[Actions(アクション)]>[Flows(フロー)]に移動し、次のコンテンツを含むアクションを作成します。
CLIENTS_WITH_MFA変数には、このアクションを適用するアプリケーションのクライアントIDが含まれます。必要ない場合は、クライアントID(および後続のif条件)を削除できます。event.transaction.requested_scopesプロパティには、認証要求が要求したすべてのスコープが含まれます。値transfer:fundsが含まれている場合は、context.multifactorプロパティを適切な値に設定してMFAを要求します。この場合、プッシュを使用してMFAを要求しています。
アプリを構成
ユーザーが資金を送金するという高額取引を実行しようとしているかどうかに応じて、適切な認証要求をAPIに送信するようにアプリを構成します。2つの認証要求(MFAの有無)の唯一の違いはスコープであることに注意してください。-
MFAあり:
export const codeExample1 =
https://{yourDomain}/authorize? audience=https://my-banking-api& scope=openid%20view:balance%20transfer:funds& response_type=id_token%20token& client_id={yourClientId}& redirect_uri={https://yourApp/callback}& nonce=NONCE& state=OPAQUE_VALUE;
-
MFAなし:
export const codeExample2 =
https://{yourDomain}/authorize? audience=https://my-banking-api& scope=openid%20view:balance& response_type=id_token%20token& client_id={yourClientId}& redirect_uri={https://yourApp/callback}& nonce=NONCE& state=OPAQUE_VALUE;
| パラメーター | 設定 |
|---|---|
audience | APIの Identifier(識別子) に設定する(」API設定」を参照)。当方ではhttps://my-banking-apiに設定しています。 |
response_type | id_token tokenに設定して、応答でIDトークンとアクセストークンを両方取得するようにします。 |
client_id | アプリケーションのクライアントIDに設定します(「アプリケーション設定」を参照)。 |
redirect_uri | 認証後にAuth0がリダイレクトで戻すアプリケーション内のURLに設定します(アプリケーション設定を参照)。 |
nonce | Auth0からの応答に含まれる安全な文字列値に設定します。これはトークンリプレイ攻撃の防止に使用され、response_type=id_token tokenには必須です。 |
state | アプリケーションにリダイレクトで戻すときにAuth0が含める不透明な値に設定します。アプリケーションはCSRF攻撃を防ぐためにこの値を使用する必要があります。 |
APIを構成する
受信トークンを検証し、承認された権限を確認するようにAPIを構成します。-
次のAPIの2つのエンドポイントを構成します。
GET /balance: 現在の残高を取得しますPOST /transfer: 資金を送金します -
Node.jsと次の複数のモジュールを使用します。- Express: Express Webアプリケーションフレームワークを追加します。
- jwks-rsa: JWKS (JSON Web Key Set)エンドポイントからRSA署名キーを取得します。
expressJwtSecretを使用すると、JWTヘッダーのkidに基づいてexpress-jwtに適切な署名キーを発行するシークレットプロバイダーを生成できます。 - express-jwt: Node.jsアプリケーションでJWTトークンを使用してHTTP要求を認証できます。JWTを使用した作業を容易にする、いくつかの機能が提供されています。
- express-jwt-authz: アクセストークンに特定のスコープが含まれているかどうかを確認します。
-
次の依存関係をインストールします。
npm install express express-jwt jwks-rsa express-jwt-authz --save -
APIエンドポイントを定義し、アクセストークンを検証するミドルウェア関数を作成し、そのミドルウェアを使用してエンドポイントを保護します。
server.jsファイル内のコードは、次のサンプルスクリプトのようになります。
- エンドポイントは
checkJwtミドルウェアを呼び出します。 express-jwtはトークンをデコードし、要求、ヘッダー、ペイロードをjwksRsa.expressJwtSecretに渡します。jwks-rsaはJWKSエンドポイントからすべての署名キーをダウンロードし、署名キーの1つがアクセストークンのヘッダー内のkidと一致するかどうかを確認します。署名キーのいずれも受信kidと一致しない場合は、エラーがスローされます。一致する場合は、正しい署名キーをexpress-jwtに渡します。express-jwtは独自のロジックを続行して、トークンの署名、有効期限、対象ユーザー、発行者を検証します。jwtAuthzは、エンドポイントに必要なスコープがアクセストークンの一部であるかどうかを確認します。指定されたスコープがアクセストークンにない場合、要求は403エラーメッセージで拒否されます。