📝

supabaseでAuthのUserを削除、公式だけではわからなかったのでいろいろ調べた件

2022/07/14に公開

supabaseでAuthのUserを削除する場合は、公式にもあるように、service_role keyをつかって
サーバーサイドで処理をする必要がある。
https://supabase.com/docs/reference/javascript/auth-api-deleteuser

ただ、公式だけをみても、具体的にどうすればよくわからず、いろいろ調べた結果
以下のような対応をしました。

./pages/api/deleteUser.ts

import { supabase } from '../../utils/supabase'
import { createClient } from '@supabase/supabase-js'
import { NextApiRequest, NextApiResponse } from 'next'

const supabaseServer = createClient(
  process.env.NEXT_PUBLIC_SUPABASE_URL as string,
  process.env.SERVICE_ROLE_KEY as string
)

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
  const { user } = await supabase.auth.api.getUserByCookie(req)
  if (user) {
    const { data: deletedUser, error } = await supabaseServer.auth.api.deleteUser(user.id)

    if (error) {
      console.log(error.message)
      return res.status(401).send(error)
    }

    return res.status(200).send(deletedUser)
  }
}

ポイントとしては、service_role key をつかって、サーバー処理用のSupabaseのクライアントを作ること。
削除用のuser.idを取得する必要があるので、こちらは、SUPABASE_ANON_KEYをつかって、別の名前でSupabaseのクライアントを作ります。

但し、これだけでは、エラーとなります。
以下の対応をして、セッション認証をしておく必要があります。

./pages/api/setSupabaseCookie.ts

import { supabase } from "../../utils/supabase"
import { NextApiRequest, NextApiResponse } from 'next'

const handler = async (req: NextApiRequest, res: NextApiResponse) => {
    await supabase.auth.api.setAuthCookie(req,res)
}

export default handler

/pages/_app.tsx

// 一部抜粋

function MyApp({ Component, pageProps }: AppProps) {
  const [user, setUser] = useState(supabase.auth.user())
  const [session, setSession] = useState(supabase.auth.session())

  useEffect(() => {
    axios.post('/api/setSupabaseCookie', {
      event: user ? 'SIGNED_IN' : 'SIGNED_OUT',
      session: supabase.auth.session(),
    })
    if (user) {
      getProfile()
    }
  }, [user])

  useEffect(() => {
    const { data: authListener } = supabase.auth.onAuthStateChange((event, session) => {
      setSession(session)
      setUser(session?.user ?? null)
    })
    return () => {
      authListener?.unsubscribe()
    }
  }, [])


  //  以下省略

}


ここまでで準備が完了したので、UI側にdelete関数を記述します。

/member/index.tsx

  const deleteUser = async () => {
    let confirmDelete = confirm(`${t.memberShipDeleteAlert1}`)
    if (confirmDelete) {
      const { data, error }: { data: any; error: any } = await axios.get('/api/deleteUser')
      if (error) {
        console.log(error.message)
        alert(error.message)
        supabase.auth.signOut()
        router.replace('/auth/signup')
      } else {
        supabase.auth.signOut()
        alert(`${t.memberShipDeleteAlert2}`)
        router.replace('/')
      }
    }
  }



その他、会員情報を削除する場合は、supabaseのon delete cascadeを設定しておきます。

これで、ユーザー退会機能を実装することができました。

参考になった情報。
Pass Supabase Session Cookie to API Route to Identify User
https://egghead.io/lessons/supabase-pass-supabase-session-cookie-to-api-route-to-identify-user

Discussion