LoginSignup
1
2

【中編】Next.jsでログインフォームを実装する 〜firebase authentication編〜

Last updated at Posted at 2023-09-03

概要

前編に引き続き、Next.jsのログインフォームについて中編です!
今回は、firebaseの初期設定をして、authに新規登録して、ログインすることとcloud firestoreにユーザ情報を格納するまでを実装していこうと思います!
前回の記事
前編 chakra-ui×react-hook-form編

中編 firebase authentication編 ←今回の記事です
後編 バリデーションとトリガー編

使用する技術は以下になります。

  • Next.js
  • chakra-ui
  • react-hook-form
  • firebase
    • authentication
    • cloud firestore
    • cloud functions

firebaseの初期設定

前回までで、サインイン画面、サインアップ画面の画面の実装までを終えています。
本記事ではfirebaseとの接続を設定していきます。この章では、firebaseの新規プロジェクト作成と、初期設定について説明していきます。
まずは、firebaseのコンソールから、新規プロジェクトを作成していきます。

1. プロジェクトの作成

プロジェクト名をauth-formとして作成します(名前は任意で構いません)
「続行」ボタンを押下して、次の画面に遷移します。
次の画面以降は、初期状態で「続行」、自身のアカウントを選択して、プロジェクトを新規作成します。

2. webアプリの登録

プロジェクトが作成されたら、次のような画面が表示されます。
次に、firebaseを使用するwebアプリの登録を行います。
画像の赤枠で囲まれているアイコンを押下してwebアプリを登録していきます。

アプリ名を入力して「アプリを登録」ボタンを押下します。
※Hostingについて今回は、チェックをつけていませんが、今後利用する予定があれば、チェックをつけてください

登録すると、Firebase SDKが表示され、npm installコマンドと接続に必要なkeyが表示されると思います。
このkeyはNext.jsのプロジェクトとfirebaseの接続で使用します。他人に知られてしまうと悪用されたり、第三者がfirebaseに接続できてしまうので、扱いには注意が必要です!

3. Authenticationの有効化

それでは次に、firebase authenticationを有効化し、今回、Email/Password認証を使って実装していくので、認証プロバイダーを有効化していきましょう。
authenticationはサイドバーの「構築」タブにあるので、押下します。

「始める」ボタンでauthenticationを利用することができます。

「メール/パスワード」を選択して、有効化します。
※パスワードなしでログインもありますが、これは無効の状態にしておいてください。

これで、firebase側のauthenticationの設定は完了です!

Next.jsとfirebaseの接続

次は、設定したfirebaseのプロジェクトをNext.jsでも使用できるように設定をしていきます。
まずは、firebaseで生成したkeyをNext.jsで使用できるように環境変数として値を格納しておきます。

1. パッケージのインストール

firebaseのメソッドや型をNext.jsで使用するために、下記のコマンドを実行して、パッケージをインストールします。

npm install firebase

2. 環境変数の設定

Next.jsプロジェクトの最上層に.envファイルを作成します。

.env
# firebase
NEXT_PUBLIC_FIREBASE_API_KEY='自身のfirebaseプロジェクトのapiKey'
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN='自身のfirebaseプロジェクトのauthDomain'
NEXT_PUBLIC_FIREBASE_PROJECT_ID='自身のfirebaseプロジェクトのprojectId'
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET='自身のfirebaseプロジェクトのstorageBucket'
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID='自身のfirebaseプロジェクトのmessagingSenderId'
NEXT_PUBLIC_FIREBASE_APP_ID='自身のfirebaseプロジェクトのappId'

2. firebase config

環境変数の準備ができたので、firebaseの初期化をしていきます!下記のフォルダ構成で実装します。

src
 ├ app
 ├ common
 └ lib
     └ firebase
         ├ apis
         │  ├ auth.ts 
         │  └ user.ts
         └ config.ts

firebaseの初期化はconfig.tsで設定します

config.ts
import { initializeApp } from 'firebase/app'
import { getAuth } from 'firebase/auth'
import { getFirestore } from 'firebase/firestore'

export const firebaseConfig = {
  apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
  authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
  projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
  storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
  messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
  appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
}

const app = initializeApp(firebaseConfig)
export const auth = getAuth(app)
export const db = getFirestore(app)

これで、firebaseとNext.jsの接続の手順が完了しました。
正常にauthに登録されるかどうか確かめてみましょう。

フォームとfirebaseの接続

実際に、authにユーザを登録する処理を実装していきます。

src
 ├ app
 ├ common
 └ lib
     └ firebase
         ├ apis
         │  ├ auth.ts //←ここに実装
         │  └ user.ts
         └ config.ts

Email/Passwordの認証メソッドをそれぞれ宣言します。(ログアウト処理も一応宣言しておきます。)

import {
  createUserWithEmailAndPassword,
  signInWithEmailAndPassword,
  signOut,
} from 'firebase/auth'

import { auth } from '@/lib/firebase/config'

/**
 * EmailとPasswordでサインイン
 * @param email
 * @param password
 * @returns Promise<boolean>
 */
export const signInWithEmail = async (args: {
  email: string
  password: string
}): Promise<boolean> => {
  let result: boolean = false
  try {
    const user = await signInWithEmailAndPassword(
      auth,
      args.email,
      args.password
    )

    if (user) {
      result = true
    }
  } catch (error) {
    result = false
    console.log(error)
  }
  return result
}

/**
 * EmailとPasswordでサインアップ
 * @param username
 * @param email
 * @param password
 * @returns Promise<boolean>
 */
export const signUpWithEmail = async (args: {
  email: string
  password: string
}): Promise<boolean> => {
  let result: boolean = false
  try {
    const user = await createUserWithEmailAndPassword(
      auth,
      args.email,
      args.password
    )
    if (user) {
      result = true
    }
  } catch (error) {
    result = false
    console.log(error)
  }
  return result
}

/**
 * ログアウト処理
 * @returns Promise<boolean>
 */
export const logout = async (): Promise<boolean> => {
  let result: boolean = false

  await signOut(auth)
    .then(() => {
      result = true
    })
    .catch((error) => {
      console.log(error)
      result = false
    })

  return result
}

auth処理が実装できたら、ログインフォームで入力された値を使って、auth処理を呼び出していきたいと思います。

signin/page.tsx
..省略..
/** サインイン画面
 * @screenname SignInScreen
 * @description ユーザのサインインを行う画面
 */
export default function SignInScreen() {
  const { handleSubmit, register } = useForm<formInputs>()

  const [show, setShow] = useState<boolean>(false)

  const onSubmit = handleSubmit(async (data) => {
    /** ここから処理追加 */
    signInWithEmail({ email: data.email, password: data.password }).then(
      (res: boolean) => {
        if (res) {
          console.log('ログイン成功')
        } else {
          console.log('ログイン失敗')
        }
      }
    )
  })
  return (..省略..)
}

ログインが成功したら、コンソールに「ログイン成功」、失敗したら、「ログイン失敗」の文言が表示されます。
続いて、サインアップ画面に処理を追加していきます。

signup/page.tsx
..省略..
/** サインアップ画面
 * @screenname SignUpScreen
 * @description ユーザの新規登録を行う画面
 */
export default function SignUpScreen() {
  const { handleSubmit, register } = useForm<formInputs>()

  const [password, setPassword] = useState(false)
  const [confirm, setConfirm] = useState(false)

  const onSubmit = handleSubmit(async (data) => {
    /** ここから処理追加 */
    signUpWithEmail({ email: data.email, password: data.password }).then(
      (res: boolean) => {
        if (res) {
          console.log('新規登録成功')
        } else {
          console.log('新規登録失敗')
        }
      }
    )
  })

  const passwordClick = () => setPassword(!password)
  const confirmClick = () => setConfirm(!confirm)

  return (..省略..)
}

サインアップでも、同様にonSubmitメソッドで新規登録処理を呼び出します。
これで、フォームとfirebaseのauth処理との接続ができました!
実際に画面を操作して、ユーザが新規登録されるか、そして、作成したユーザでログインできるかを確かめてみましょう!

firebaseをnpm installすると、Module not found: Can't resolve 'encoding' ...というエラーがコンソールに表示されます。されない方はそのままで問題ありませんが、表示されている方はnpm i -D encodingをコマンドで実行してみてください!

下記の入力情報で、新規作成を実施してみます。

コンソールに「新規登録成功」と表示されています!※2回押しちゃってんで、2回目はエラーが出てます。

firebase consoleを確認してみます!ユーザが追加されていることがわかります!

これでfirebase authenticationにユーザ登録完了です!
では、追加された後にユーザ情報をcloud firestoreに格納する処理を追加しましょう!
まずは、firestoreを有効化します!「データベース作成」から、本番環境、地域を東京で選択してfirestoreを使用できるように設定します

firestoreは初期設定で、セキュリティルールの設定で、権限がない状態にあるので、まずは、フル権限で設定しておきます。

ここまで設定できたら、サインアップ処理にコードを追加します!

apis/auth.tsx
/**
 * EmailとPasswordでサインアップ
 * @param username
 * @param email
 * @param password
 * @returns Promise<boolean>
 */
export const signUpWithEmail = async (args: {
  email: string
  password: string
}): Promise<boolean> => {
  let result: boolean = false
  try {
    const user = await createUserWithEmailAndPassword(
      auth,
      args.email,
      args.password
    ).then(async (userCredential) => {
      /** thenから追加します */
      /** cloud firestoreのコレクション */
      const colRef = doc(db, 'users', userCredential.user.uid)
      /** document追加 */
      await setDoc(colRef, {
        uid: userCredential.user.uid,
        email: userCredential.user.email,
      })
      return userCredential.user
    })
    if (user) {
      result = true
    }
  } catch (error) {
    result = false
    console.log(error)
  }
  return result
}

別ユーザの情報で、再度新規登録してみます

コンソール、authentication、firestoreで確認してみましょう!

コンソール

authentication

firestore

全て新規登録されていますね!これで、新規作成処理は完了です!次はログイン処理を確認してましょう!

ログイン処理

下記の情報でフォームを入力します。

コンソールで「ログイン成功」が表示されました!これで完了です!

おわりに

これでフォームからユーザの新規登録、ログイン処理までの流れを実装できました!
auth周りの最低限の機能はこれで全てになります!ログアウトについても、処理自体は掲載しているので、ボタンを配置して、処理を呼び出せばログアウトすることができます。
後編では、authのエラーハンドリングやバリデーションエラーについて実装、説明していきます!

最後まで読んでいただきありがとうございました!

1
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2