概要
Firestoreでユーザーのプロファイル(情報)を保存し、Authenticationで認証を行う方法が
まとまっていなかったので記事にしました!
前提:Firebaseコンソールからプロジェクトの設定が終わっていること
考え方
考え方としては、以下のようになります!
- AuthでsignUpする
- AuthのcurrentUserを取得する
- 取得した情報をFirestoreに保存する
Firestoreに保存する情報は、Authenticationの一意なIDであるuid
を使います!
実装
config
プロジェクト作成時に提示される内容をコピーします。
APIキーなどは漏れて不正利用されると大変なので
.env
に保存しておきます。
→Firestoreのセキュリティルールを変更しましょう。
Nextで.env
に保存するときはNEXT_PUBLIC_
で始まる環境変数でないといけません
// Import the functions you need from the SDKs you need
import { initializeApp } from 'firebase/app'
// TODO: Add SDKs for Firebase products that you want to use
// https://firebase.google.com/docs/web/setup#available-libraries
// Your web app's Firebase configuration
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,
databaseURL: process.env.NEXT_PUBLIC_DB_URL,
}
// Initialize Firebase
export const app = initializeApp(firebaseConfig)
Firestoreにデータを保存する関数
こちらもほぼ公式ドキュメント通りにコピペします。
import { app } from '~/utils/Firebase/config'
import { getFirestore, addDoc } from 'firebase/firestore'
// Initialize Cloud Firestore and get a reference to the service
const db = getFirestore(app)
export const insertData = async (table: string, data: Object) => {
try {
const docRef = await addDoc(collection(db, table), data)
console.log('Document written with ID: ', docRef.id)
} catch (e) {
console.error('Error adding document: ', e)
}
}
signUp
関数の実装
ここでも公式のドキュメント通りに実装します。
(エラーの検知用フラグを入れるなど、若干工夫をしています)
import {
createUserWithEmailAndPassword,
getAuth,
} from 'firebase/auth'
import { UserResponse } from '~/types/user'
import { app } from '~/utils/Firebase/config'
const auth = getAuth(app)
export const authSignUp = async (email: string, password: string) => {
let response = undefined
let isError = false
await createUserWithEmailAndPassword(auth, email, password)
.then((userCredential) => {
// Signed in
const user = userCredential.user
response = user
})
.catch((error: ErrorEvent) => {
response = error.message
console.error(response)
isError = true
})
return { isError, response }
}
フォーム部分はreact-hook-form
を採用しています。
UIの話は今回はしないので、サインアップボタン押下後に動作する関数を見てみましょう。
サインアップボタン押下後の関数
コード
const signUp = useCallback(async () => {
const values = getValues()
const { isError, response } = await authSignUp(
values['mail'],
values['password']
)
if (isError) {
alert(response)
return
}
const currentUser = getAuth().currentUser
const user = {
name: values['name'],
role: RoleType.student,
uid: currentUser!.uid,
}
await insertData('users', user)
}, [])
解説
流れに沿って見てみましょう。
authのsignUp
const { isError, response } = await authSignUp(
では
先ほど作成した関数を用いてAuthentication自体のサインアップを行います。
Firebase AuthenticationのsignUp
関数はサインアップと同時にサインインも
行ってくれるので、ここでsignIn
の関数を実行する必要はありません🙌
currentUser
const currentUser = getAuth().currentUser
では
アプリのFirebase Authenticationの情報を取得し、
現在サインインしているユーザーを取得します。
このcurrentUserにはuid
以外の情報も含まれているので
気になる方はドキュメントを見てみてください〜
userオブジェクト
const user = {
name: values['name'],
role: RoleType.student,
uid: currentUser!.uid,
}
ユーザーオブジェクトには、Firestoreに保存したい情報を格納します。
メールアドレスとパスワードはAuthenticationの方で保存しているので
Firestoreには保存せず、名前、役割、uid
程度で留めておきます。
insertData
こちらは最初に作成した関数です。
Firestoreの任意のテーブル(コレクション)でドキュメント(データ)を追加するもので
今回は、users
コレクションに名前と役割、uid
を保存します。
終わりに
いかがでしたか?
流れを理解し、Authenticationの知識を持っていれば
意外にも簡単に実装できました!
みなさんももし使う機会があれば、遊んでみてください〜✨
それでは👋
参考文献