ロゴテキスト ロゴ

    【Middleware使用】Next.js12でBasic認証を導入(ローカル,vercel 両対応)

    【Middleware使用】Next.js12でBasic認証を導入(ローカル,vercel 両対応)

    Next.js ver13系ではこの記事の方法が使えなくなりました。

    13系の人は以下記事を参考にしてみて下さいmm






    Next.jsのversion12から Middleware と呼ばれるものが導入されました。




    Middlewareについて簡単に書くと、


    pagesフォルダの特定フォルダ配下に _middleware.js(tsももちろんOK)を配置すると

    リクエスト完了前に実行してくれる、というもの。

    ユーザーのリクエストをもとに、レスポンスの書き換え、リダイレクト、ヘッダーの追加、HTMLのストリーミングなどをおこなうことができます。


    Middleware | Next.js より引用(DeepL翻訳)





    Next.js ver11まで_app.tsxでBasic認証を設定する方法が一般的なイメージでしたが




    _appではなく、Middlewareを利用する事で特定のフォルダのみBasic認証をかけるといった事が容易に出来るようになります!


    下記のケースだとadmin/配下のみBasic認証をかける事が出来るようになります、便利ですね☺️

    pages/
      index.tsx
      about.tsx
      admin/ #このフォルダ配下にはBasic認証がかかる
        index.tsx
        setting.tsx
        _middleware.ts #Basic認証を設定
        ・・・

    検証した環境

    1 nextjs 12.0.10

    色々な使い方が出来るよ、という事で公式から参考のコードが公開されています

    examples/edge-functions at main · vercel/examples




    Next.js12にBasic認証を導入する

    以下がBasic認証を行うための _middleware.ts の全文になります!

    pages/_middleware.ts
    import { NextRequest, NextResponse } from 'next/server'
     
    export const middleware = (req: NextRequest) => {
      if (process.env.ENABLE_BASIC_AUTH !== 'true') {
        return NextResponse.next()
      }
     
      const basicAuth = req.headers.get('authorization')
     
      if (basicAuth) {
        const auth = basicAuth.split(' ')[1]
        const [user, password] = Buffer.from(auth, 'base64').toString().split(':')
     
        if (user === process.env.BASIC_AUTH_USER && password === process.env.BASIC_AUTH_PASSWORD) {
          return NextResponse.next()
        }
      }
     
      return new Response('Auth required', {
        status: 401,
        headers: {
          'WWW-Authenticate': 'Basic realm="Secure Area"',
        },
      })
    }


    あとは .env と next.config.js に環境変数を読み込めるようにします

    .env
    ENABLE_BASIC_AUTH="false"
    BASIC_AUTH_USER="user"
    BASIC_AUTH_PASSWORD="password"
    next.config.js
    module.exports = {
      reactStrictMode: false,
      env: {
        ENABLE_BASIC_AUTH: process.env.ENABLE_BASIC_AUTH,
        BASIC_AUTH_USER: process.env.BASIC_AUTH_USER,
        BASIC_AUTH_PASSWORD: process.env.BASIC_AUTH_PASSWORD,
      },
    }



    これで全ページでBasic認証が設定出来ます!





    Vercelで設定する

    Vercelでプロジェクトを選択し

    Settings > Environment Variables

    で環境変数に値を設定します。



    これで先程と同じようにVercelでもBasic認証がかけられるようになります。





    余談(Vercel以外での_middlewareについて)

    この記事を書いていた少し前(2022/02月初旬頃)に


    Serverless Next.js+ Next.js12 + AWS(CloudFront + S3 + Lambda)

    という構成でNext.jsのシステムを構築していました。


    パッケージバージョン
    serverless2.71.0
    @sls-next/serverless-component3.6.0
    next12.0.9


    当時、上記の構成で同じように_middleware.tsを使ってBasic認証をかけようとしたところ

    Basic認証のキャンセルボタンを押下するとエラー画面ではなく通常通りページが開けてしまう、という問題がありました。





    serverlessはアップデートの頻度が多く開発速度が速いイメージがあるため

    既に直っているかもしれませんが、

    Vercelだと出来るけど、Serverless Next.js + AWSだと出来ない」というものがちょこちょこあった印象です。


    (↓のような記事も上がってますね)

    Next.jsのmiddlewareはVercel以外でも問題なく使えるか





    結局下記のNext.js11までのBasic認証のかけ方で対応出来たので難を逃れたのですが


    Next.jsのデプロイ先はVercelが安定する。

    逆にVercel以外でNext.jsを動かすのは結構なチャレンジになる、というのを当時実感していました😅

    プロフィールの背景画像 プロフィール画像
    Yuki Takara
    都内でフリーランスのエンジニアをやってます。フロントとアプリ開発メインに幅広くやってます。