🍆

Next.js(App Router)とauth-helpersでユーザー削除処理の書き方の例(退会処理)

2023/12/14に公開

Next.jsのApp Router と Supabaseのauth-helpers-nextjs を使ったユーザー削除処理の記述に関するエントリーが不足していると思いますので、僕も書き残しておこうと思います。

1. .envファイルに記述を追加する

ユーザー削除の際には「SERVICE_ROLE」というものが必要になります。
ローカル環境(Supabase CLI)では、 supabase status を叩いたときに出てくる「service_role_key」のことです。

本番環境のSupabaseでは上記に示した箇所にあります。

これを Next.js の .env ファイルとして記述を追加しておきます。

.env
NEXT_ADMIN_SUPABASE_SERVICE_ROLE=【ここにservice_role_key】

環境変数の名前は何でもいいですが、明確に分かる名前にしておくと良いですね!今回は「NEXT_ADMIN_SUPABASE_SERVICE_ROLE」としておきました。

2. API Routesで削除用のAPIエンドポイントを用意する

今回は /src/app/auth/user/delete/[user_id]/route.ts にファイルを用意しました。ここに退会処理を書いていきます。

route.ts
import { createRouteHandlerClient } from "@supabase/auth-helpers-nextjs";
import { cookies } from "next/headers";
import { NextResponse } from "next/server";
import { NextRequest } from "next/server";
import type { Database } from "@/components/Types/Supabase/schema";

export async function GET(req: NextRequest, { params }: { params: { user_id: string } }) {
  const cookieStore = cookies();
  // 削除の権限があるクライアント操作であることを示す
  const supabase = createRouteHandlerClient<Database>(
    { cookies: () => cookieStore },
    {
      supabaseKey: process.env.NEXT_ADMIN_SUPABASE_SERVICE_ROLE,
    }
  );
  // リクエストを叩いたユーザーの情報を取得する(Cookieが渡っているので自動で取得される)
  const user = await supabase.auth.getUser();
  
  // パスを叩いたユーザーが本人であるかを一応チェックしておく(パスにuser_idを付けないと、イタズラでリンク踏まされたときが怖い気がしたので。)
  if (user && user.data.user && user.data.user.id === params.user_id) {
    // 削除を実行
    const { data, error } = await supabase.auth.admin.deleteUser(user.data.user.id);
    if (data) { // 成功
      return NextResponse.json({
        status: "success",
        message: `アカウント削除しました。`,
      });
    }
  }

  // 失敗
  return NextResponse.json({
    "status": "error",
    "message": "アカウントの削除ができませんでした。"
  });
}

3. アカウント削除を実行する

あとは http://localhost:3000/auth/user/delete/【ここにユーザーのID】 にアクセスするとアカウント削除が実行されます。

http://localhost:3000/auth/user/delete/ を実行パスにしても良かったのですが、こうするとイタズラで貼られた http://localhost:3000/auth/user/delete/ のリンクを踏んでしまうと、意図せずにアカウント削除の被害に合ってしまうかなと思ったためです。(あ、POSTにすりゃいいのか...)

ユーザーIDは基本的に他者には露出しないもの(させるべきではないもの)なので、イタズラ的にリンクを踏まされる可能性は極端に低いものと思います。

【ちなみに】ユーザーが紐づいたデータは自動で削除される

テーブルカラム作成時に Cascade にしておくとユーザーが紐づいたデータが自動で削除されるようになります。ユーザーを削除するだけで関連データが勝手に全て消えてくれて超便利です!

おわりに

アカウント削除だけはフロントエンドだけでは実行できません。
サーバー側の力を借りる必要がありますが、そんなに大量に行われる処理ではないので仕方がないものだと割り切ってしまいましょう!

Discussion