Node.js API の実装 (SPA + API)
ステップ 1. API のエンドポイントを定義する
package.json ファイルを作成する
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 を参照してください。
エンドポイントを実装する
server.js ファイルを作成します。コードでは次のことを行います。
- 依存関係を取得する。
- エンドポイントを実装する。
- API サーバーを起動する。
node server で API サーバーを起動し、localhost:8080/timesheets に HTTP POST リクエストを送信します。This is the POST /timesheets endpoint というメッセージを含む JSON レスポンスが返されるはずです。
これでエンドポイントは用意できましたが、現時点では誰でも呼び出せてしまいます。これをどう解決するかは、次の段落に進んで確認してください。
ステップ 2. API エンドポイントを保護する
jwt 関数と、シークレットを取得するための jwks-rsa を使用します。これらのライブラリは次のように動作します。
express-jwtがトークンをデコードし、リクエスト、ヘッダー、ペイロードをjwksRsa.expressJwtSecretに渡します。- 次に
jwks-rsaが JWKS エンドポイントからすべての署名鍵をダウンロードし、そのいずれかが JWT ヘッダー内のkidと一致するかを確認します。受け取ったkidに一致する署名鍵がない場合は、エラーがスローされます。一致するものが見つかれば、正しい署名鍵をexpress-jwtに渡します。 - その後
express-jwtが処理を続け、トークンの署名、有効期限、audience、issuerを検証します。
- を検証するミドルウェア関数を作成する。
- ルートでそのミドルウェアを使えるようにする。
localhost:8080/timesheets に HTTP POST を行うと、Missing or invalid token というエラーメッセージが返されるはずです (リクエストでアクセストークンを送信していないので、これはまったく問題ありません) 。
正常に動作するケースもテストするには、次のことを行う必要があります。
- アクセストークンを取得する。取得方法の詳細については、Get an Access Token を参照してください。
- リクエストに
Authorizationヘッダーを追加し、その値をBearer ACCESS_TOKENに設定して API を呼び出す (ここでACCESS_TOKENは最初の手順で取得したトークンの値です) 。
ステップ 3. アプリケーションの権限を確認する
scope) をアプリケーションが持っているかどうかを確認する機能を実装に追加します。特に、トークンに正しいscope、つまり batch:upload が含まれていることを確認します。
そのために、express-jwt-authz Node.js パッケージを使用するので、プロジェクトに追加してください:
jwtAuthz(...) の呼び出しを追加するだけで済みます。
追加の依存関係が 1 つ必要です。express-jwt-authz ライブラリは express-jwt と組み合わせて使用され、JWT を検証するとともに、目的の エンドポイント を呼び出すために必要な permissions が含まれていることを確認します。詳しくは、express-jwt-authz GitHub repository を参照してください。
以下はサンプル実装です (一部のコードは簡潔にするため省略しています) :
403とともに、Forbidden というエラーメッセージが返されるはずです。これは、APIからこのscopeを削除することで確認できます。
ステップ 4. ユーザーを識別する
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 として使用できます。