Skip to main content

Node.js API の実装 (SPA + API)

このドキュメントは SPA + API アーキテクチャシナリオ の一部で、Node.js で API を実装する方法を説明しています。実装されているソリューションの詳細については、このシナリオを参照してください。 Node.js API 実装の完全なソースコードは、こちらの GitHub リポジトリで確認できます。

ステップ 1. API のエンドポイントを定義する

Node.js API の構築には、Express Webアプリケーションフレームワークを使用します。

package.json ファイルを作成する

API 用のフォルダーを作成し、そのフォルダーに移動して npm init を実行します。これで package.json ファイルが作成されます。 デフォルトの設定のままでも、必要に応じて変更してもかまいません。 このサンプルの package.json は以下のようになります。

依存関係をインストールする

次に、依存関係を設定します。使用するモジュールは次のとおりです。
  • express: このモジュールは Express Webアプリケーションフレームワーク を追加します。
  • cors: このモジュールは、CORS を有効にするためのサポートを追加します。API は、Web ブラウザー上で別のドメインで動作する Single-Page Application から呼び出されるため、これが必要です。
  • jwks-rsa: このライブラリは、JWKS (JSON Web Key Set) エンドポイントから RSA 署名鍵を取得します。expressJwtSecret を使用すると、 ヘッダー内の kid に基づいて、express-jwt に適切な署名鍵を渡す secret provider を生成できます。詳細については、node-jwks-rsa GitHub repository を参照してください。
  • express-jwt: このモジュールを使うと、Node.js アプリケーションで JWT トークンを使用して HTTP リクエストを認証できます。また、JWT を扱いやすくするための関数もいくつか提供されています。詳細については、express-jwt GitHub repository を参照してください。
  • body-parser: これは Node.js のリクエストボディを解析するミドルウェアです。受信したリクエストストリームの body 全体を抽出し、扱いやすい形で req.body として利用できるようにします。詳細といくつかの代替手段については、body-parser GitHub repository を参照してください。
これらの依存関係をインストールするには、次を実行します。

エンドポイントを実装する

API ディレクトリに移動し、server.js ファイルを作成します。コードでは次のことを行います。
  • 依存関係を取得する。
  • エンドポイントを実装する。
  • API サーバーを起動する。
以下はサンプル実装です。
node server で API サーバーを起動し、localhost:8080/timesheets に HTTP POST リクエストを送信します。This is the POST /timesheets endpoint というメッセージを含む JSON レスポンスが返されるはずです。 これでエンドポイントは用意できましたが、現時点では誰でも呼び出せてしまいます。これをどう解決するかは、次の段落に進んで確認してください。

ステップ 2. API エンドポイントを保護する

トークンを検証するには、express-jwt middleware が提供する jwt 関数と、シークレットを取得するための jwks-rsa を使用します。これらのライブラリは次のように動作します。
  1. express-jwt がトークンをデコードし、リクエスト、ヘッダー、ペイロードを jwksRsa.expressJwtSecret に渡します。
  2. 次に jwks-rsa が JWKS エンドポイントからすべての署名鍵をダウンロードし、そのいずれかが JWT ヘッダー内の kid と一致するかを確認します。受け取った kid に一致する署名鍵がない場合は、エラーがスローされます。一致するものが見つかれば、正しい署名鍵を express-jwt に渡します。
  3. その後 express-jwt が処理を続け、トークンの署名、有効期限、audienceissuer を検証します。
コードで行う手順は次のとおりです。
  • を検証するミドルウェア関数を作成する。
  • ルートでそのミドルウェアを使えるようにする。
実際にタイムシートをデータベースに保存するコードを追加することもできます。以下はサンプル実装です (一部のコードは簡潔にするため省略しています) 。 ここでサーバーを起動し、localhost:8080/timesheets に HTTP POST を行うと、Missing or invalid token というエラーメッセージが返されるはずです (リクエストでアクセストークンを送信していないので、これはまったく問題ありません) 。 正常に動作するケースもテストするには、次のことを行う必要があります。
  • アクセストークンを取得する。取得方法の詳細については、Get an Access Token を参照してください。
  • リクエストに Authorization ヘッダーを追加し、その値を Bearer ACCESS_TOKEN に設定して API を呼び出す (ここで ACCESS_TOKEN は最初の手順で取得したトークンの値です) 。

ステップ 3. アプリケーションの権限を確認する

このステップでは、タイムシートを作成するためにこのエンドポイントを利用できるpermissions (または scope) をアプリケーションが持っているかどうかを確認する機能を実装に追加します。特に、トークンに正しいscope、つまり batch:upload が含まれていることを確認します。 そのために、express-jwt-authz Node.js パッケージを使用するので、プロジェクトに追加してください:
これで、特定の エンドポイント を実行するために JWT に特定の scope が含まれていることを確認するには、ミドルウェアに jwtAuthz(...) の呼び出しを追加するだけで済みます。 追加の依存関係が 1 つ必要です。express-jwt-authz ライブラリは express-jwt と組み合わせて使用され、JWT を検証するとともに、目的の エンドポイント を呼び出すために必要な permissions が含まれていることを確認します。詳しくは、express-jwt-authz GitHub repository を参照してください。 以下はサンプル実装です (一部のコードは簡潔にするため省略しています) :
このscopeを含まないトークンでAPIを呼び出すと、HTTPステータスコード403とともに、Forbidden というエラーメッセージが返されるはずです。これは、APIからこのscopeを削除することで確認できます。

ステップ 4. ユーザーを識別する

JWT の検証に使用される express-jwt ミドルウェアは、JWT に含まれる情報を req.auth にも設定します。ユーザーを一意に識別するために sub クレームを使いたい場合は、req.auth.sub をそのまま使用できます。 ただし、timesheets アプリケーションでは、ユーザーのメールアドレスを一意の識別子として使用したいと考えています。 まず最初に、ユーザーのメールアドレスを アクセストークン に追加するルールを作成する必要があります。Dashboard の Rules section に移動し、Create Rule ボタンをクリックします。 ルールには、たとえば Add email to Access Token のようなわかりやすい名前を付け、次のコードを使用します。
namespace は、claim に一意の名前を付け、標準の OIDC claim の名前と重複しないようにするために使われます。ただし、Auth0 では、名前空間付きと名前空間なしの両方のカスタム claim をサポートしています。カスタム claim の詳細については、Create Custom Claims を参照してください。 次に、API 内で req.auth から claim の値を取得し、タイムシートのエントリに関連付ける一意のユーザー ID として使用できます。