VercelのMiddlewareを使って非Next.jsプロジェクトにBasic認証をかける
プロトタイピングしたツールを、身内へ気軽に公開したくなることってありますよね。Cloudflare Accessみたいなちゃんとしたソリューションをイチから導入するほどのモチベーションはなくて、Basic 認証が付いてればまあいっか、くらいの気軽さのやつです。
近頃だと、筆者はフロントエンドプロジェクトを Vercel にデプロイすることが多いので、Vercel について調べてみました。
Vercel には、主に Next.js から使うことを前提とした、Edge Middleware という仕組みがあります。これはページの表示前に割り込む形で通信結果に介入できるので、Basic 認証を実装できそうです。
Next.js を使う場合はこれでいいのですが、目的次第ではCreate React AppやViteのような、小さめのツールチェインでプロトタイピングをしたいケースもありますよね。そういった場合にも Edge Middleware で Basic 認証を使えると嬉しそうです。
幸いなことに、ドキュメントを読むと Next.js を使わない方法も解説されていました。
ベータ版とのことなので、前述の Next.js 向けの API と同じく今後は変更が入る可能性もありますが、ひとまずこれを使ってみましょう。
Next.js 向けの実装との違い
Next.js 版を参考にして、非 Next.js 向けの Edge Middleware を実装していきます。Next.js 向けの最新版と比べると一つ古い API で提供されているようなので、参考にする記事もひとつ前のものにします。
また、前述した公式ドキュメントの quickstart では "Vercel CLI" のタブを参考にして進めます。
1. トップレベルに middleware.js を設置する
まずは、プロジェクトのトップレベルに middleware.js
というファイルを設置します。Vercel のビルドプロセスはこの名前のファイルがあると Edge Middleware の実装ファイルとして読み込もうとします。
ひとまず、前述の記事のサンプルコードをコピペしておいてください。(import 文は Next.js に依存しているので消していいです)
@vercel/edge
をインストールして next()
を置き換える
2. Next.js 向けの実装では NextResponse.next()
となっている部分が非 Next.js プロジェクトでは利用できないので、代わりになる実装を用意します。 @vercel/edge
にそれっぽい実装が生えているようです。
これは使わせてもらいましょう。 @vercel/edge
をインストールします。
$ npm install @vercel/edge
インストールしたら、 middleware.js
でインポートしておきます。
import { next } from "@vercel/edge";
Edge Middleware は ES Modules 対応なので、普通に import 文を使って OK です。
import したら、 NextResponse.next()
を置き換えます。
- return NextResponse.next();
+ return next();
これで OK です。
3. Buffer を atob に置き換え
さて、これで動くかなと思いきや、動かしてみるとエラーが出ます。 Buffer
がないようです。
Edge Middleware のランタイムで使用できる API を確認してみましょう。
残念ながら Buffer
は生えていないようですが、今回は Basic 認証の Base 64 デコードを行いたいだけなので、 atob
関数があれば事足りそうです。
- const [user, password] = Buffer.from(basicAuth, 'base64').toString().split(':')
+ const [user, password] = atob(basicAuth).toString().split(":");
これでできました!
全体像
最終的に、次のようなコードになりました。
import { next } from "@vercel/edge";
export const config = {
matcher: "/",
};
export default function middleware(request) {
const authorizationHeader = request.headers.get("authorization");
if (authorizationHeader) {
const basicAuth = authorizationHeader.split(" ")[1];
const [user, password] = atob(basicAuth).toString().split(":");
if (user === process.env.BASIC_AUTH_USER && password === process.env.BASIC_AUTH_PASSWORD) {
return next();
}
}
return new Response("Basic Auth required", {
status: 401,
headers: {
"WWW-Authenticate": 'Basic realm="Secure Area"',
},
});
}
このコードを動かすために必要な準備は、次の 3 つです。
- プロジェクトのトップレベルに上記の
middleware.js
を設置する -
@vercel/edge
をインストールする - Vercel の環境変数に
BASIC_AUTH_USER
とBASIC_AUTH_PASSWORD
を設定する
あとは通常の Vercel のデプロイを行えば、Edge Middleware が動き始めます。
まとめ
Next.js を使わなくても Edge Middleware を利用できるのは地味に嬉しいですね。
ちょっとしたアプリケーションでも Next.js を使ってしまいがちではありますが、こういった小技が使える様になれば、Vite 等も選択しやすくなりそうです。
宣伝
株式会社モニクルでは、はたらく世代・子育て世代がお金の不安を手放せる手助けをするための金融サービス業をより広めるために、ソフトウェアエンジニアを募集しています。
90 秒だけお時間をいただいて、↓ の動画を見ていただけると、どんなサービスをやっている会社なのかざっくりわかってもらえると思います。
マネイロにお金の相談をしにきてくださるだけでも嬉しいですし、もしこの記事を読んで会社自体にも興味を持っていただけたら、↓ の Culture Deck(会社説明資料)を読んでみてください。
さらに興味を持ってもらえた方は Meety で私と雑談しましょう!
よろしくお願いします!
Discussion
viteプロジェクトでも動作できるよう実装できました!
ありがとうございました
素晴しい記事を本当にありがとうございました!
docsify への組み込みにはプラスαで手順が必要だったので、備忘録として派生記事を書いてみました。
本当に助かりました!