【中編】Next.jsでログインフォームを実装する 〜firebase authentication編〜
概要
前編に引き続き、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
ファイルを作成します。
# 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
で設定します
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処理を呼び出していきたいと思います。
..省略..
/** サインイン画面
* @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 (..省略..)
}
ログインが成功したら、コンソールに「ログイン成功」、失敗したら、「ログイン失敗」の文言が表示されます。
続いて、サインアップ画面に処理を追加していきます。
..省略..
/** サインアップ画面
* @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処理との接続ができました!
実際に画面を操作して、ユーザが新規登録されるか、そして、作成したユーザでログインできるかを確かめてみましょう!
下記の入力情報で、新規作成を実施してみます。
コンソールに「新規登録成功」と表示されています!※2回押しちゃってんで、2回目はエラーが出てます。
firebase consoleを確認してみます!ユーザが追加されていることがわかります!
これでfirebase authenticationにユーザ登録完了です!
では、追加された後にユーザ情報をcloud firestoreに格納する処理を追加しましょう!
まずは、firestoreを有効化します!「データベース作成」から、本番環境、地域を東京で選択してfirestoreを使用できるように設定します
firestoreは初期設定で、セキュリティルールの設定で、権限がない状態にあるので、まずは、フル権限で設定しておきます。
ここまで設定できたら、サインアップ処理にコードを追加します!
/**
* 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のエラーハンドリングやバリデーションエラーについて実装、説明していきます!
最後まで読んでいただきありがとうございました!
Discussion