サーバーアプリ+API:APIのためのNode.jsの実装

サーバー+APIアーキテクチャーシナリオの一環として、Node.jsでタイムシートAPIを実装する方法について説明します。実装したソリューションについての情報は、シナリオを参照してください。

Node.js APIの実装で使用する全ソースコードは、こちらのGitHubリポジトリでご覧いただけます。

1.APIエンドポイントを定義する

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

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

API用のフォルダーを作成しそこに移動してnpm initを実行します。これにより、package.jsonファイルがセットアップされます。

デフォルト設定のままにするか、必要に応じて変更します。

サンプルのpackage.jsonは次のようになります。

{
  "name": "timesheets-api",
  "version": "1.0.0",
  "description": "API used to add timesheet entries for employees and contractors",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/auth0-samples/auth0-pnp-timesheets.git"
  },
  "author": "Auth0",
  "license": "MIT",
  "bugs": {
    "url": "https://github.com/auth0-samples/auth0-pnp-timesheets/issues"
  },
  "homepage": "https://github.com/auth0-samples/auth0-pnp-timesheets#readme"
}

Was this helpful?

/

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

次に、依存関係を設定する必要があります。以下のモジュールを使用します。

  • express:このモジュールはExpress Webアプリケーションフレームワークを追加します。

  • jwks-rsa:このライブラリーは、JWKS(JSON Web Key Set)エンドポイントからRSA署名鍵を取得します。expressJwtSecretを使用するとJWTヘッダーのkidに基づいてexpress-jwtに正しい署名鍵を提供するシークレットプロバイダーを生成することができます。詳細については、「node-jwks-rsa GitHubリポジトリ」を参照してください。

  • express-jwt:このモジュールは、Node.jsアプリケーションでJWTトークンを使用してHTTP要求を認証します。JWTを使用した作業を容易にする、いくつかの機能が提供されています。詳細については「express-jwt GitHubリポジトリ」を参照してください。

  • body-parser:これはNode.js本文解析ミドルウェアです。やり取りが簡単なものとして、受信要求ストリームから本文全部を抽出し、req.bodyで公開します。詳細および代替については、 「body-parser GitHubリポジトリ」を参照してください。

これらの依存関係をインストールするには、次を実行します。

npm install express express-jwt jwks-rsa body-parser --save

Was this helpful?

/

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

APIディレクトリに移動し、server.jsファイルを作成します。コードに必要なこと:

  • 依存関係を設定する。

  • 要求本文解析ミドルウェアを有効にする。

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

  • APIサーバーを起動する。

実装例を以下に示します。

// set dependencies
const express = require('express');
const app = express();
const jwt = require('express-jwt');
const jwksRsa = require('jwks-rsa');
const bodyParser = require('body-parser');

// enable the use of request body parsing middleware
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
  extended: true
}));

// create timesheets upload API endpoint
app.post('/timesheets/upload', function(req, res){
  res.status(201).send({message: "This is the POST /timesheets/upload endpoint"});
})

// launch the API Server at localhost:8080
app.listen(8080);

Was this helpful?

/

node serverを使用してAPIサーバーを起動し、localhost:8080/timesheets/uploadにHTTP POST要求を行います。「This is the POST /timesheets/upload endpoint」というメッセージを含むJSON応答が表示されます。

これでエンドポイントが入手できましたが、それは誰でも呼び出すことができます。次の段落に進んで、この問題を解決する方法を確認します。

2. APIエンドポイントをセキュリティ保護する

トークンを検証するには、express-jwtミドルウェアが提供するjwt関数とjwks-rsaパッケージを使用してAuth0から公開鍵を取得します。ライブラリーは以下を行います。

  1. express-jwtはトークンをデコードし、要求、ヘッダー、ペイロードをjwksRsa.expressJwtSecretに渡します。

  2. その後jwks-rsaはJWKSエンドポイントからすべての署名鍵をダウンロードし、署名鍵の1つがJWTヘッダーのkidと一致するかどうかを確認します。どの署名鍵も受け取ったkidに一致しない場合、エラーがスローされます。一致するものがあれば、express-jwtに正しい署名鍵を渡します。

  3. express-jwtはトークンの署名、有効期限、audienceissuerを検証する独自のロジックを継続します。

コードでは次の手順に従います。

  • アクセストークンを検証するミドルウェア関数を作成する。

  • ルートでミドルウェアを使用できるようにする。

これはまた、タイムシートエントリーをローカルデータベースまたは、希望する他のストレージメカニズムに保存するロジックを実装する良い機会でもあります。以下はサンプル実装を示します(簡潔にするために一部のコードは省略しています)。

// set dependencies - code omitted

// enable the use of request body parsing middleware - code omitted

// Create middleware for checking the JWT
const checkJwt = jwt({
  // Dynamically provide a signing key based on the kid in the header and the signing keys provided by the JWKS endpoint.
  secret: jwksRsa.expressJwtSecret({
    cache: true,
    rateLimit: true,
    jwksRequestsPerMinute: 5,
    jwksUri: `https://{yourDomain}/.well-known/jwks.json`
  }),

  // Validate the audience and the issuer.
  audience: process.env.AUTH0_AUDIENCE,
  issuer: `https://{yourDomain}/`,
  algorithms: ['RS256']
});

// create timesheets API endpoint
app.post('/timesheets/upload', checkJwt, function(req, res){
  var timesheet = req.body;

  // Save the timesheet entry to the database...

  //send the response
  res.status(201).send(timesheet);
})

// launch the API Server at localhost:8080 - code omitted

Was this helpful?

/

ここでサーバーを起動してlocalhost:8080/timesheetsにHTTP POSTを実行すると、エラーメッセージMissing or invalid tokenが表示されるはずです(要求でアクセストークンを送信しなかったためこれは正確です)。

また、作業シナリオをテストするためには、次を実行する必要があります。

  • アクセストークンを取得する。詳しい取得方法については、以下をご覧ください:アクセストークンを取得する

  • APIを呼び出し、値Bearer ACCESS_TOKENを指定してAuthorizationヘッダーを要求に追加します(ACCESS_TOKENは最初の手順で取得したトークンの値)。

3. クライアントの権限を確認する

この手順では、クライアントに権限(またはスコープ)があるかを確認する機能を実装に追加して、タイムシートをアップロードするためにエンドポイントを使用します。特にトークンのスコープが正しく、batch:uploadであることを確認することが目的です。

そのためには、express-jwt-authz Node.jsパッケージを利用するので、それをプロジェクトに追加します。

npm install express-jwt-authz --save

Was this helpful?

/

ここでjwtAuthz (...)への呼び出しをミドルウェアに追加して、特定のエンドポイントを実行するために、特定のスコープがJWTに含まれていることを確認します。以下はサンプル実装を示します(簡潔にするために一部のコードは省略しています)。

// set dependencies - some code omitted
const jwtAuthz = require('express-jwt-authz');

// Create middleware for checking the JWT

// Enable the use of request body parsing middleware
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
  extended: true
}));

// Batch upload endpoint
app.post('/timesheets/upload', checkJwt, jwtAuthz(['batch:upload']), function(req, res){
  var timesheet = req.body;

  // Save the timesheet entry to the database...

  //send the response
  res.status(201).send(timesheet);
});

// launch the API Server at localhost:8080 - code omitted

Was this helpful?

/

このスコープを含まないトークンを使用してAPIを呼び出すHTTPステータスコード403の「Forbidden(禁止)」というエラーメッセージが表示されます。APIからこのスコープを削除すると、これをテストすることができます。

これで作業完了です!完了です。