암호 재설정 및 메일 주소 변경

54510 단어 FirebaseTypeScripttech
시스템의 암호 변경과 메일 주소 변경이 막혀서 글을 씁니다

컨디션

  • firebase v9.x
  • 암호 인증
  • react-hook-form v7.x
  • zod v3.x
  • chakra v1.x
  • 해당 부분


    암호 변경


    https://firebase.google.com/docs/auth/web/manage-users?hl=ja#set_a_users_password

    전자 메일 주소 변경


    https://firebase.google.com/docs/auth/web/manage-users?hl=ja#set_a_users_email_address

    사용자 재인증


    https://firebase.google.com/docs/auth/web/manage-users?hl=ja#re-authenticate_a_user
    공식적인 것은 때로는 진지하고, 때로는 남에게 밀려나 고통스럽다

    무슨 문제 있어요?


    계정 삭제, 메인 메일 주소 설정, 비밀번호 변경 등 보안에 중요한 작업을 하려면 사용자가 최근에 로그인해야 한다.
    중요: 사용자는 최근에 로그인하여 사용자의 전자 우편 주소를 설정해야 합니다.사용자의 재인증증을 보십시오.
    중요: 사용자는 최근에 로그인해서 사용자 비밀번호를 설정해야 합니다.사용자의 재인증증을 보십시오.
    !?
    즉, 비밀번호와 메일주소를 바꾸려면 먼저 재인증이 필요하다는 것이다.
    re-authenticate_a_user
    import { getAuth, reauthenticateWithCredential } from "firebase/auth";
    
    const auth = getAuth();
    const user = auth.currentUser;
    
    // TODO(you): prompt the user to re-provide their sign-in credentials
    const credential = promptForCredentials();
    
    reauthenticateWithCredential(user, credential).then(() => {
      // User re-authenticated.
    }).catch((error) => {
      // An error ocurred
      // ...
    });
    
    !?
    갑자기 TODO에 적혀있는promptForCredentials(),어디서 얻을지 모르겠다credential😂

    WithCredential에 던진 credential 획득


    https://stackoverflow.com/questions/37811684/how-to-create-credential-object-needed-by-firebase-web-user-reauthenticatewith
    v9에서 Email AuthProvider에서 credential을 받은 글 발견😎
    const credential = EmailAuthProvider.credential(
        auth.currentUser.email,
        userProvidedPassword
    )
    
    즉, 아래의 구조를 만들어 처리하면 된다.
  • 현재 사용자 확보(getAuth().currentUser)
  • 현재 사용자로부터 받은 메일 주소 및 설정(user?.email ?? '')
  • 암호를 입력하십시오(password).
  • credential(EmailAuthProvider.credential) 획득
  • credential을 사용하여 1과 4에서 취득한 사용자와 재인증(reauthenticateWithCredential)
  • import { FirebaseError } from '@firebase/util'
    import {
      EmailAuthProvider,
      getAuth,
      reauthenticateWithCredential,
    } from 'firebase/auth'
    
    (async () => {
      const user = getAuth().currentUser
      try {
        const credential = await EmailAuthProvider.credential(
          user?.email ?? '', 
          password
        )
        user && (await reauthenticateWithCredential(user, credential))
        //メールアドレス、パスワードリセットの処理
      } catch (e) {
        if (e instanceof FirebaseError) {
          console.error(e)
        }
      }
    })()
    

    form과 핵심 부분만 설치


    암호 변경


    import { FirebaseError } from '@firebase/util'
    import { zodResolver } from '@hookform/resolvers/zod'
    import {
      EmailAuthProvider,
      getAuth,
      reauthenticateWithCredential,
      updateEmail,
    } from 'firebase/auth'
    import { useForm } from 'react-hook-form'
    import { z } from 'zod'
    
    /**
     * 簡易バリデーション
     */
    const schema = z.object({
      newEmail: z.string().email(),
      password: z.string().min(6),
    })
    
    type UpdateEmailInput = z.infer<typeof schema>
    
    /**
     * @see https://firebase.google.com/docs/auth/web/manage-users?hl=ja#set_a_users_email_address
     * @see https://firebase.google.com/docs/auth/web/manage-users?hl=ja#re-authenticate_a_user
     * @see https://stackoverflow.com/questions/37811684/how-to-create-credential-object-needed-by-firebase-web-user-reauthenticatewith
     * firebaseのメールアドレスを変更をする関数
     * 成功
     * 1. EmailAuthProvider.credential(firebaseにログインさせcredentialを取得する)
     * 2. reauthenticateWithCredential(credentialを使いfirebaseを再認証させる)
     * 3. updateEmail(パスワードを再設定する)
     * 失敗
     * 1. firebaseのエラーを吐く
     */
    export const useUpdateEmail = () => {
      const form = useForm<UpdateEmailInput>({
        defaultValues: {
          newEmail: '',
          password: '',
        },
        resolver: zodResolver(schema),
      })
    
      const onUpdateEmail = form.handleSubmit(async ({ newEmail, password }) => {
        const user = getAuth().currentUser
        try {
          const credential = await EmailAuthProvider.credential(
            user?.email ?? '',
            password
          )
          user && (await reauthenticateWithCredential(user, credential))
          user && (await updateEmail(user, newEmail))
          form.setValue('newEmail', '')
          form.setValue('password', '')
        } catch (e) {
          form.setValue('password', '')
          if (e instanceof FirebaseError) {
            console.error(e)
          }
        }
      })
      return {
        form,
        onUpdateEmail,
      }
    }
    
    const UpdatePassword = () => {
      const {
        form: { register },
        onUpdatePassword,
      } = useUpdatePassword()
    
      return (
        <Box borderWidth={1} p={4}>
          <Heading size={'md'}>パスワード変更</Heading>
          <FormControl>
            <Input placeholder={'今のPW'} {...register('password')} />
          </FormControl>
          <FormControl >
            <Input placeholder={'新しいPW'} {...register('newPassword')} />
          </FormControl>
          <FormControl >
            <Input placeholder={'新しいPW確認'} {...register('newPasswordConfirm')} />
          </FormControl>
          <Button onClick={onUpdatePassword}>
            パスワード変更
          </Button>
        </Box>
      )
    }
    

    전자 메일 주소 변경


    import { FirebaseError } from '@firebase/util'
    import { zodResolver } from '@hookform/resolvers/zod'
    import {
      EmailAuthProvider,
      getAuth,
      reauthenticateWithCredential,
      updatePassword,
    } from 'firebase/auth'
    import { useForm } from 'react-hook-form'
    import { z } from 'zod'
    
    /**
     * 簡易バリデーション
     */
    const schema = z
      .object({
        newPassword: z.string().min(6),
        newPasswordConfirm: z.string().min(6),
        password: z.string().min(6),
      })
      .refine((data) => data.newPassword === data.newPasswordConfirm, {
        message: "Passwords don't match",
        path: ['newPasswordConfirm'],
      })
    
    type UpdatePasswordInput = z.infer<typeof schema>
    
    /**
     * @see https://firebase.google.com/docs/auth/web/manage-users?hl=ja#set_a_users_password
     * @see https://firebase.google.com/docs/auth/web/manage-users?hl=ja#re-authenticate_a_user
     * @see https://stackoverflow.com/questions/37811684/how-to-create-credential-object-needed-by-firebase-web-user-reauthenticatewith
     * firebaseのパスワードを変更をする関数
     * 成功
     * 1. EmailAuthProvider.credential(firebaseにログインさせcredentialを取得する)
     * 2. reauthenticateWithCredential(credentialを使いfirebaseを再認証させる)
     * 3. updatePassword(パスワードを再設定する)
     * 失敗
     * 1. firebaseのエラーを吐く
     */
    export const useUpdatePassword = () => {
      const form = useForm<UpdatePasswordInput>({
        defaultValues: {
          newPassword: '',
          newPasswordConfirm: '',
          password: '',
        },
        resolver: zodResolver(schema),
      })
    
      const onUpdatePassword = form.handleSubmit(
        async ({ newPassword, password }) => {
          const user = getAuth().currentUser
          try {
            const credential = await EmailAuthProvider.credential(
              user?.email ?? '',
              password
            )
            user && (await reauthenticateWithCredential(user, credential))
            user && (await updatePassword(user, newPassword))
          } catch (e) {
            if (e instanceof FirebaseError) {
              console.error(e)
            }
          } finally {
            form.setValue('password', '')
            form.setValue('newPassword', '')
            form.setValue('newPasswordConfirm', '')
          }
        }
      )
      return {
        form,
        onUpdatePassword,
      }
    }
    
    const UpdateEmail = () => {
      const {
        form: { register },
        onUpdateEmail,
      } = useUpdateEmail()
      return (
        <Box borderWidth={1} p={4}>
          <Heading size={'md'}>メールアドレス変更</Heading>
          <FormControl>
            <Input placeholder={'今のPW'} {...register('password')} />
          </FormControl>
          <FormControl>
            <Input placeholder={'新しいメアド'} type={'email'} {...register('newEmail')} />
          </FormControl>
          <Button onClick={onUpdateEmail}>
            メールアドレス変更
          </Button>
        </Box>
      )
    }
    

    최후


    validation, 오류 처리,loading 등을 절대 잊지 마세요!!


    암호 재설정


    import { FirebaseError } from '@firebase/util'
    import { zodResolver } from '@hookform/resolvers/zod'
    import { getAuth, sendPasswordResetEmail } from 'firebase/auth'
    import { useForm } from 'react-hook-form'
    import { z } from 'zod'
    
    /**
     * 簡易バリデーション
     */
    const schema = z.object({
      email: z.string().email(),
    })
    
    type SendPasswordResetEmailInput = z.infer<typeof schema>
    
    
    /**
     * @see https://firebase.google.com/docs/auth/web/manage-users?hl=ja#send_a_password_reset_email
     * firebaseのパスワードリセットをする関数
     * 成功
     * 1. 指定したメールアドレスにパスワードをリセットするメールを送信
     * 失敗
     * 1. firebaseのエラーを吐く
     */
    export const useSendPasswordResetEmail = () => {
      const form = useForm<SendPasswordResetEmailInput>({
        defaultValues: {
          email: '',
        },
        resolver: zodResolver(schema),
      })
    
      const onSendPasswordResetEmail = form.handleSubmit(async ({ email }) => {
        try {
          await sendPasswordResetEmail(getAuth(), email)
          form.setValue('email', '')
        } catch (e) {
          if (e instanceof FirebaseError) {
            console.error(e)
          }
        }
      })
      return {
        form,
        onSendPasswordResetEmail,
      }
    }
    
    const SendPasswordResetEmail = () => {
      const {
        form: { register },
        onSendPasswordResetEmail,
      } = useSendPasswordResetEmail()
      return (
        <Box borderWidth={1} p={4}>
          <Heading size={'md'}>パスワードリセット</Heading>
          <FormControl>
            <Input placeholder={'リセットするユーザーのメアド'} {...register('email')} />
          </FormControl>
          <Button onClick={onSendPasswordResetEmail}>
            リセット
          </Button>
        </Box>
      )
    }
    

    좋은 웹페이지 즐겨찾기