🔒

Next.js App Router + Supabase でセッションがなければログイン画面にリダイレクトさせる

2023/11/01に公開
2

2023/11/01追記
@supabase/ssrに対応しました。


Next.js と Supabase Auth Helpers でセッションがなければログイン画面にリダイレクトさせる

Next.jsSupabase Auth Helpers で認証機能つきのアプリケーションを作成中です。

セッションがなければミドルウェアの処理の時点でログイン画面にリダイレクトさせる処理を書こうと思い、公式サンプルの middleware.ts に追記してみました。

まず Supabase の公式サンプルですが、セッションを維持するにあたり、以下のように middleware.ts を記述しておくと良いようです。
(middleware.ts は app フォルダと同階層に配置します)

https://supabase.com/docs/guides/auth/auth-helpers/nextjs#managing-session-with-middleware

/src/middleware.ts
import { createMiddlewareClient } from '@supabase/auth-helpers-nextjs'
import { NextResponse } from 'next/server'

import type { NextRequest } from 'next/server'
import type { Database } from '@/lib/database.types'

export async function middleware(req: NextRequest) {
  const res = NextResponse.next()
  const supabase = createMiddlewareClient<Database>({ req, res })
  await supabase.auth.getSession()
  return res
}

次に追記の方法ですが、stack overflow に参考になる記事がありました。

以下のように条件分岐でリダイレクトさせてあげればよさそうです。記事にある通り、最初に「_next」の条件を作って return しておかないと正しくパスを判定できずコンソールエラーが起きます。(matcher で絞り込んでも OK です)

/src/middleware.ts
import { createMiddlewareClient } from '@supabase/auth-helpers-nextjs'
import { NextResponse } from 'next/server'

import type { NextRequest } from 'next/server'
import type { Database } from '@/lib/database.types'

export async function middleware(req: NextRequest) {
  const res = NextResponse.next()
  const supabase = createMiddlewareClient<Database>({ req, res })
-  await supabase.auth.getSession()
+  const {
+    data: { session },
+  } = await supabase.auth.getSession();
+  if (req.url.includes('_next')) return;
+  if (!session && !req.url.includes('/login')) {
+    return NextResponse.redirect(new URL('/login', req.url));
+  }
+  if (session && req.url.includes('/login')) {
+    return NextResponse.redirect(new URL('/', req.url));
+  }
  return res
}

と思っていたら、Auth Helpers が非推奨になりました(2023/11/01)

まさか記事を書いてから1週間で使えなくなるとは…
まあ、Auth Helpers 自体がベータ版でしたし仕方ありません。

今後は @supabase/ssr パッケージを使ってくださいとのことです。

ということで、 @supabase/ssr パッケージに対応します。
まずは以下のコマンドを使います。

npm uninstall @supabase/auth-helpers-nextjs
npm install @supabase/ssr

次に以下のコマンドで公式サンプルを出力します。

npx create-next-app -e with-supabase

次に、サンプルから以下のフォルダとファイルを自分のプロジェクトにコピーして置き換えます。

  • app/auth フォルダ
  • utils フォルダ
  • middleware.ts

次に、環境変数に値が入っていることを確認してから middleware.ts 内の try-catch を外します。

最後に middleware.ts を以下のように書き換えて完了です。

middleware.ts
・・・

  // Refresh session if expired - required for Server Components
  // https://supabase.com/docs/guides/auth/auth-helpers/nextjs#managing-session-with-middleware
-  await supabase.auth.getSession();

+  // リダイレクト処理
+  const {
+    data: { session },
+  } = await supabase.auth.getSession();
+  if (!session && !request.url.includes("/login")) {
+    return NextResponse.redirect(new URL("/login", request.url));
+  }
+  if (session && request.url.includes("/login")) {
+    return NextResponse.redirect(new URL("/", request.url));
+  }

  // If the session was refreshed, the request and response cookies will have been updated
  // If the session was not refreshed, the request and response cookies will be unchanged
  return response;
}

+export const config = {
+  matcher: ["/((?!auth|_next/static|_next/image|favicon.ico).*)"],
+};

Discussion

Qiushi PanQiushi Pan

非推薦になったという情報はどこに載っているでしょうか? ソースを提示していただけると助かります。