Auth0でExpress.jsのAPIに認証を追加する

Auth0でExpress.jsのAPIに認証を追加する

2024-04-16

この記事ではAuth0を使ってExpress.jsのAPIに認可を追加する方法を解説します。

以下の公式ドキュメントに沿って実践した内容を記載しています。

https://auth0.com/docs/quickstart/backend/nodejs/interactive

目次

Auth0ダッシュボードでのAPIの作成

Auth0ダッシュボードでAPIを作成します。

Application -> APIs -> Create APIで作成。

  • Name: なんでも良い
  • Identifier: なんでも良い(公開されている必要もない)
  • Signing Algorithm: 何もなければRS256が良い(非対称なので)

Permissionの追加

APIを作成したら、対象APIのPermissionsタブでPermissionを追加する。

今回は以下2つを作成した。

  • read:order(注文情報の読み取り)
  • create:order(注文情報の作成)

Node.js APIの作成

Express.jsを使ってWebAPIを作成します。

なお、細かいExpressの使い方等については説明は行いません。

まずはプロジェクトディレクトリに移動して、以下のコマンドを実行。

npm init -y

expressのインストールをします。

npm install express

次にserver.jsを作成し、中身は次の様にします。

const express = require('express');
const app = express();

const port = process.env.PORT || 8080;

app.get('/orders', (req, res) => {
  res.json({
    'message': 'Get all orders!!'
  });
});

app.post('/orders', (req, res) => {
  res.json({
    'message': 'Create a order!!'
  });
});

app.listen(port);

console.log('Running on port ', port);

環境変数を使いたいので、以下をインストール

npm install dotenv --save

server.jsの先頭に以下を追加

require('dotenv').config()

.envファイルを作成し、以下を追加 PORT=3000

以下コマンドを実行して、サーバーを起動 node server.js

localhost:3000/ordersにアクセスすると設定したメッセージが取得できるはず。

認証の追加

続いて作成したAPIに認証を追加します。

まずはjwtの検証に必要なパッケージのインストールを行います。

npm install --save express-oauth2-jwt-bearer

ミドルウェアの設定

server.jsを次の様に変更

require('dotenv').config();
const express = require('express');
const app = express();

// 追加
const { auth, requiredScopes } = require('express-oauth2-jwt-bearer');

// 追加
const checkJwt = auth({
  audience: process.env.AUDIENCE,
  issuerBaseURL: process.env.ISSUER_BASE_URL
});

const port = process.env.PORT || 8080;

...省略

上記の変更ではリクエストに含まれるアクセストークンが有効かどうかをチェックする。トークンが有効でない場合は401: Authorizationエラーが発生する。

この変更ではトークンがリクエストされたリソースにアクセスするために必要なスコープを持っているかどうかはチェックしない。

エンドポイントの保護

エンドポイントの保護を行うポイントは以下

  • checkJwtをミドルウェアとして渡すことで、有効なアクセストークンを持つ場合のみアクセス可能とする
  • requiredScopesを使って、スコープのチェックも可能

server.jsを次の様に変更する。

...省略
// 追加
app.get('/public', (req, res) => {
  res.json({
    'message': 'Public endpoint'
  });
});

// 追加
// checkJwtを使って、アクセストークンが有効な場合のみアクセス可能
app.get('/private', checkJwt, (req, res) => {
  res.json({
    'message': 'private endpoint'
  });
});

// 追加
// read:orders スコープを持つかチェックする
const checkReadOrders = requiredScopes('read:order');

// 有効なアクセストークンとスコープを持っているか確認する
app.get('/orders', checkJwt, checkReadOrders, (req, res) => { // 変更
  res.json({
    'message': 'Get all orders!!'
  });
});

const checkCreateOrder = requiredScopes('create:order');

app.post('/orders', checkJwt, checkCreateOrder, (req, res) => { // 変更
  res.json({
    'message': 'Create a order!!'
  });
});

...省略

「node server.js」でサーバーを立ち上げると「localhost:3000/public」にはアクセスできるが、それ以外のエンドポイントにはアクセスできないことが確認できる。

アクセストークンの取得

Auth0ダッシュボードのAPIのTestタブに行くとアクセストークンが取得できる。以下のコマンドを実行すると、privateエンドポイントからレスポンスを受け取れる

curl --request GET \
  --url http://localhost:3000/private/ \
  --header 'authorization: Bearer your_access_token

それでもスコープが必要なエンドポイントにはアクセスできない。

Next Step

  • スコープを追加したアクセストークンを取得する方法を調査する
  • クライアントアプリ(React, Next.jsなど)に認証・認可を追加して、APIを叩く
  • ここを読む