見出し画像

Firebaseでユーザー退会処理を実現する方法

こんにちは、阿部健太朗です。

この記事では、

Firebaseを使用した時
どのようにしてユーザー退会処理を行うのか解説します。

【前提】


私は下記の記事を参考にSNSを開発しました。

ChatApp(β版)

基本的な仕様については下記記事をご覧ください。

「FirebaseとTypeScriptとNext.jsを使ってリアルタイムチャットアプリを作ろう」
https://zenn.dev/hisho/books/617d8f9d6bd78b

上記の記事では以下の処理を解説しています。

・会員登録
・投稿
・サインイン
・サインアウト

【本題】


上記の「Chapter13 [実装編]Headerを整えよう」にて
src/componet/Header/Header.tsxを完成させました。

import {
  Avatar,
  Button,
  chakra,
  Container,
  Flex,
  Heading,
  Menu,
  MenuButton,
  MenuItem,
  MenuList,
  Spacer,
  useToast,
} from '@chakra-ui/react'
import { useAuthContext } from '@src/feature/auth/provider/AuthProvider'
import { FirebaseError } from '@firebase/util'
import { getAuth, signOut } from 'firebase/auth'
import { useRouter } from 'next/router'
import Link from 'next/link'

export const Header = () => {
  const { user } = useAuthContext()
  const toast = useToast()
  const { push } = useRouter()

  const handleSignOut = async () => {
    try {
      const auth = getAuth()
      await signOut(auth)
      toast({
        title: 'ログアウトしました。',
        status: 'success',
        position: 'top',
      })
      push('/signin')
    } catch (e) {
      if (e instanceof FirebaseError) {
        console.log(e)
      }
    }
  }

  return (
    <chakra.header py={4} bgColor={'blue.600'}>
      <Container maxW={'container.lg'}>
        <Flex>
          <Link href={'/'} passHref>
            <chakra.a
              _hover={{
                opacity: 0.8,
              }}
            >
              <Heading color={'white'}>Firebase Realtime Chat</Heading>
            </chakra.a>
          </Link>
          <Spacer aria-hidden />
          {user ? (
            <Menu>
              <MenuButton>
                <Avatar flexShrink={0} width={10} height={10} />
              </MenuButton>
              <MenuList py={0}>
                <MenuItem onClick={handleSignOut}>サインアウト</MenuItem>
              </MenuList>
            </Menu>
          ) : (
            <Link href={'/signin'} passHref>
              <Button as={'a'} colorScheme={'teal'}>
                サインイン
              </Button>
            </Link>
          )}
        </Flex>
      </Container>
    </chakra.header>
  )
}

上記のコードはユーザーがログインした時のヘッダーをユーザーの状態に応じて変化させるコードになります。

参考記事ではユーザーがサインインした時、サインアウトしか表示されません。

そのため、サインインしたユーザーが退会することができません。

そのままではWebサービスとして未完成のため、「ユーザー退会処理」を考えました。

import {
  Avatar,
  Button,
  chakra,
  Container,
  Flex,
  Heading,
  Menu,
  MenuButton,
  MenuItem,
  MenuList,
  Spacer,
  useToast,
} from '@chakra-ui/react'
import { useAuthContext } from '@/feature/auth/provider/AuthProvider'
import { FirebaseError } from '@firebase/util'
import { getAuth, deleteUser, signOut } from 'firebase/auth'
import { useRouter } from 'next/router'
import Link from 'next/link'

export const Header = () => {
  const { user } = useAuthContext()
  const toast = useToast()
  const { push } = useRouter()

  // ログアウト処理
  const handleSignOut = async () => {
    try {
      const auth = getAuth()
      await signOut(auth)
      toast({
        title: 'ログアウトしました。',
        status: 'success',
        position: 'top',
      })
      push('/signin')
    } catch (e) {
      if (e instanceof FirebaseError) {
        console.log(e)
      }
    }
  }

  // ユーザー退会処理
  const handleDeleteUser = async () => {
    try {
      const auth = getAuth()
      const currentUser = auth.currentUser
      if (currentUser) {
        await deleteUser(currentUser)
        toast({
          title: '退会しました。',
          status: 'success',
          position: 'top',
        })
        push('/signin')
      }
    } catch (e) {
      if (e instanceof FirebaseError) {
        console.log(e)
      }
    }
  }

  return (
    <chakra.header py={4} bgColor={'#000000'}>
      <Container maxW={'container.lg'}>
        <Flex>
          <Link href={'/'} passHref>
            <chakra.a
              _hover={{
                opacity: 0.8,
              }}
            >
              <Heading color={'white'}>Chat App(β版)</Heading>
            </chakra.a>
          </Link>
          <Spacer aria-hidden />
          {user ? (
            <Menu>
              <MenuButton>
                <Avatar flexShrink={0} width={10} height={10} />
              </MenuButton>
              <MenuList py={0}>
                <MenuItem onClick={handleSignOut}>ログアウト</MenuItem>
                <MenuItem onClick={handleDeleteUser}>退会する</MenuItem>
              </MenuList>
            </Menu>
          ) : (
            <div style={{ display: 'flex', gap: '10px' }}>
              <Link href={'/signin'} passHref>
                <Button as={'a'} colorScheme={'blue'}>
                  ログイン
                </Button>
              </Link>
              <Link href={'/signup'} passHref>
                <Button as={'a'} colorScheme={'green'}>
                  サインアップ
                </Button>
              </Link>
            </div>
          )}
        </Flex>
      </Container>
    </chakra.header>
  )
}

答えとしては上記になります。

ユーザー退会処理の実装方法として下記記事を参考にしました。

【Firebase】ユーザーアカウントの削除方法
https://zenn.dev/rorisutarou/articles/ec6889aa82eb54

【結論】


ユーザー退会処理では

・ユーザーの認証情報が欲しい
・かつ現在ログインしているユーザーであること

が必要になります。
※間違っていたら修正します。
※要はどんなユーザー情報でも削除して良いわけではないため、一意のユーザー情報だけ削除したいのです。

  // ユーザー退会処理
  const handleDeleteUser = async () => {
    try {
      const auth = getAuth()
      const currentUser = auth.currentUser
      if (currentUser) {
        await deleteUser(currentUser)
        toast({
          title: '退会しました。',
          status: 'success',
          position: 'top',
        })
        push('/signin')
      }
    } catch (e) {
      if (e instanceof FirebaseError) {
        console.log(e)
      }
    }
  }

deleteUserメソッドはFirebaseが用意しているので使用します。


ユーザー登録

任意のメールアドレスとパスワードを登録します。

FirebaseのAuthenticationで登録されていることを確認

FirebaseのAuthenticationで任意のユーザー情報が登録されていることを確認します。


退会する

右上のアイコンから「退会する」をクリックする。


退会後の画面

その後、本当にログインできないか確認します。

ログイン失敗

念のため、Firebaseも確認します。

FirebaseのAuthenticationで登録した情報が削除されているか確認

無事、ユーザー情報が削除されています。

【おわりに】

2023年5月時点で、私はエンジニア歴2年目です。
チュートリアル系の記事をそのままやるだけでも大変でした。

少しずつ機能を理解することで、最終的にユーザー退会処理を自力で実装できました。

最近はChatGPTのような対話型AIがあるので、利用してみるのもありだと思います。
※私はめちゃ×2お世話になりました

雨のお恵みをいただければ、カナヅチが治るそう。