Lesson 8

ミドルウェアを使用してリクエスト前に処理を実行

Lesson 8 Chapter 1
ミドルウェアを使ったBasic認証機能の実装

ミドルウェアとは

本チャプターではミドルウェアを使用して処理を実行する方法について学んでいきます。
Next.jsではpagesディレクトリと同階層にmiddleware.jsファイルを作成した場合、 指定したページへのリクエストの完了前にmiddleware.jsのコードが実行されます。
その際、以下の様な流れでレスポンスの返却に至ります。

nextjs-8-1

このミドルウェアの仕組みは主に以下の様な処理に使用されます。

  • 認証機能→今回作成するベーシック認証(Basic認証)等
  • BOTからの保護
  • リダイレクト処理
  • サポートされていないブラウザへのハンドリング処理
  • 多言語への表示変更処理
  • ログイン認証やリダイレクト処理など、全てのページで同様のロジックを実装することなく一つのファイルで管理するのでとても便利な仕組みとなっています。

    Basic認証機能の実装

    ベーシック認証(Basic認証)とは

    ベーシック認証(Basic認証)とはWebサイトの特定のページやファイルにアクセス制限をかけることができる認証方法の1つです。 ベーシック認証をかけると、認証をかけたWebサイトにアクセスしようとしたとき、下の画像のような認証ダイアログが立ち上がって、ユーザー名(ID)とパスワードの入力が求められます。

    nextjs-8-2

    本レッスンでは実際にNext.jsのミドルウェア機能を使用してBasic認証機能の実装を始めていきましょう。
    初めにmiddlewareを扱うmiddleware.jsファイルを新規作成します。
    ファイルが新規作成できたら認証処理を下記の様に実装します。

    middleware.js
    import { NextResponse } from "next/server";
    
    export const config = {
        // このmiddleware処理をpage配下のどのファイルに適用させるかを指定
        matcher: ["/"],
    };
    
    export function middleware(req) {
        const basicAuth = req.headers.get("authorization");
        const url = req.nextUrl;
        // HeaderにAuthorizationが定義されているかをチェック
        if (basicAuth) {
            const authValue = basicAuth.split(" ")[1];
            const [user, pwd] = atob(authValue).split(":");
    
            // basic認証で入力された値が一致しているかチェック
            if (user === "testUser" && pwd === "password123") {
                return NextResponse.next();
            }
            // 認証失敗時
            url.pathname = "/api/authError";
            return NextResponse.rewrite(url);
        }
        // 認証をキャンセルすればエラーを返す
        url.pathname = "/api/authCancel";
        return NextResponse.rewrite(url);
    }

    上記の様に実装できたらBasic認証エラー時とキャンセル時のレスポンスを作成します。
    認証エラー時の処理はurl.pathname = "/api/authError";で指定している様にpages/api/authError.jsに以下の様に記述します。

    pages/api/authError.js
    export default function handler(req, res) {
        res.setHeader("WWW-authenticate", 'Basic realm="Secure Area"');
        res.statusCode = 402;
        res.end(`Auth Error.`);
    }

    上記の様に記述することで認証エラー時に「Auth Error.」の文字を出力させることができます。 認証キャンセル時の処理はErrorの時と同様にpages/api/authCancel.jsに以下の様に記述します。

    pages/api/authCancel.js
    export default function handler(req, res) {
        res.setHeader("WWW-authenticate", 'Basic realm="Secure Area"');
        res.statusCode = 401;
        res.end(`Auth Required.`);
    }

    上記の様に記述することで認証キャンセル時に「Auth Required.」の文字を出力させることができます。 これでBasic認証機能の実装が完了です。

    動作確認

    それではindexページにアクセスして正しくBasic認証機能が実装されているか確認していきましょう。
    indexページを認証完了したことがわかりやすい様に以下の様にコードを修正しておきます。

    index.jsx
    export default function Hello() {
      return (
        <div>  
          <h1>認証完了</h1>
        </div>
      );
    };

    実際にhttp://localhost:3000/ にアクセスし下記の様な画面遷移になれば問題なく実装完了です。

    ・認証完了時

    ・認証エラー時

    ・認証キャンセル時

    まとめ

    実際に作成してみてNext.jsのミドルウェアの機能を使用するば簡単にBasic認証機能が実装できること実感できましたでしょうか?
    ミドルウェアは認証機能の他にもたくさんの用途が存在しますので気になる方は他の用途も調べてみてはいかがでしょうか。 次のレッスンから実際にNext.jsとFirebaseを使用してTODOアプリの開発を行なっていきます。