【Firebase】Authentication（version 9）の使い方

# 前提

- [Firebase JavaScript SDK version9](https://firebase.google.com/docs/database/web/start?hl=ja)を使用
- メールアドレス、パスワードでの認証
- [Firebaseが用意しているUI](https://firebase.google.com/docs/auth/web/firebaseui?hl=ja)は使用せず独自のフォームを作成
- chrome（バージョン: 101.0.4951.54）

# 準備

1. [Firebase管理画面](https://console.firebase.google.com/project/gsdemo-95f59/authentication/providers)にアクセス
2. 「新しくプロバイダを追加」ボタンをクリック
3. 「メール・パスワード」にチェックし作成
4. 下記コードを追記

```jsx
import { getAuth, createUserWithEmailAndPassword, signInWithEmailAndPassword, onAuthStateChanged } from "https://www.gstatic.com/firebasejs/9.8.1/firebase-auth.js"
```

`getAuth, createUserWithEmailAndPassword, signInWithEmailAndPassword, onAuthStateChanged`以外のメソッドを使用する場合は `{}`内に追記する。

> [【バージョン9】**利用可能なFirebaseJSSDK（公式）**](https://firebase.google.com/docs/web/learn-more?hl=ja#available-libraries)

# ユーザー登録（サインアップ）

新規ユーザーがメールアドレスとパスワードをフォームに入力し、入力したメールアドレス、パスワードを`createUserWithEmailAndPassword` メソッドをに渡す。

```jsx
import { getAuth, createUserWithEmailAndPassword, signInWithEmailAndPassword, onAuthStateChanged } from "https://www.gstatic.com/firebasejs/9.8.1/firebase-auth.js"

document.getElementById("register_btn").addEventListener("click", registerUser);
}

const registerUser = function () {
	const $email = document.getElementById("email");
	const $password = document.getElementById("password");
	const email = $email.value;
	const password = $password.value;
	createUserWithEmailAndPassword(getAuth(), email, password)
		.then((userCredential) => {
            //登録が成功した時の処理
		})
		.catch((error) => {
			console.log(error.code);
		});
}
```

管理画面を確認しユーザーが追加されていればOK。
ユーザ登録が成功すると自動的に作成したユーザーでログインされ、`userCredential` にユーザーオブジェクト入る。
`userCredential.user` で下記のようなユーザー情報が取得できる。

```jsx
userCredential.user.accessToken //トークンを取得
userCredential.user.email       //メールアドレスを取得
userCredential.user.uid.        //ユーザーIDを取得
userCredential.user.metadata.createdAt   //ユーザー作成日時を取得
userCredential.user.metadata.lastLoginAt //最終ログイン日時を取得
```

# ログイン

既存ユーザーがメールアドレスとパスワードをフォームに入力し、入力したメールアドレス、パスワードを `signInWithEmailAndPassword` メソッドに渡す。

```jsx

import { getAuth, createUserWithEmailAndPassword, signInWithEmailAndPassword, onAuthStateChanged } from "https://www.gstatic.com/firebasejs/9.8.1/firebase-auth.js"

const loginUser = function () {
	const email = document.getElementById("email").value;
	const password = document.getElementById("password").value;
	signInWithEmailAndPassword(getAuth(), email, password)
		.then((userCredential) => {
			//ログイン時の処理を記入
		})
		.catch(() => {
			//エラー時の処理を記入
		});
}
```

ログインもサインインと同様、ログインが成功すれば `userCredential` にログインしたユーザーのオブジェクトが入る。
アクセス方法についてはユーザー登録（サインイン）を参照。

# ログアウト

ユーザーがログインしている状態でログアウトボタンを押すと、 `signOut` メソッドを実行。

```jsx
import { getAuth, signOut } from "https://www.gstatic.com/firebasejs/9.8.1/firebase-auth.js"

document.getElementById("logout_btn").addEventListener("click", logOut);

const logOut = function () {
	const auth = getAuth();
	signOut(auth).then(() => {
		//ログアウトした時の処理
	}).catch((error) => {
		//ログアウトに失敗した時の処理
	});;
}
```

# ログイン状態を監視する

`onAuthStateChanged` メソッドを使用。

- サインイン（自動的にログインされる）
- ログイン
- ログアウト
- アカウント削除（自動的にログアウトされる）
- アカウント情報更新

上記のアクションが実行されるごとにメソッドが呼び出される。
メソッドが呼び出されると、ユーザーに関する情報を取得できる。

```jsx
onAuthStateChanged(getAuth(), observeLoginUser);

const observeLoginUser = function (user) {
	//ログイン状態が変更された時の処理
}
```

ユーザーがログインしていれば`user` にログインユーザーの情報が入る。
ログインしていない場合は `null` が入る。情報アクセスは下記参照。

```jsx
user.accessToken //トークンを取得
user.email       //メールアドレスを取得
user.displayName //画面表示名を取得
user.uid.        //ユーザーIDを取得
user.photoURL    //画像のURLを取得
user.metadata.createdAt   //ユーザー作成日時を取得
user.metadata.lastLoginAt //最終ログイン日時を取得
```

# **ユーザーのプロフィールを更新**

サインインが成功した際、 `updateProfile` メソッドを使用し、ユーザーが入力したメールアドレスを加工（xxxxx@gmail.com ⇒ xxxxx）して`displayName` に設定する場合。

```jsx
import { getAuth, updateProfile } from "https://www.gstatic.com/firebasejs/9.8.1/firebase-auth.js"

document.getElementById("register_btn").addEventListener("click", registerUser);

const registerUser = function () {
    //Authオブジェクトを取得
	const auth = getAuth();
	const email = document.getElementById("email").value;
	const password = document.getElementById("password").value;

	createUserWithEmailAndPassword(auth, email, password)
		//サインイン成功時の処理
		.then(function (userCredential) {

			//updateProfileメソッドでdisplayNameに情報を登録
			updateProfile(auth.currentUser, {
				displayName: auth.currentUser.email.split('@')[0],
			})
				.then(function () {
					//ユーザー情報をアップデートできた時の処理
				}).catch(function () {
					//ユーザー情報をアップデートできなかった時の処理
				});

		}).catch(() => {
		//サインインできなかった時の処理
		});
}
```

# ログインしているユーザーの情報を取得する

`auth.currentUser` でオブジェクトを取得し、ドット記法で取得したい値を指定する。

```jsx
import { getAuth } from "https://www.gstatic.com/firebasejs/9.8.1/firebase-auth.js"

const auth = getAuth();

console.log(auth.currentUser.accessToken);
console.log(auth.currentUser.email);
console.log(auth.currentUser.uid);
console.log(auth.currentUser.photoURL);
```

# ユーザーを削除する

ログイン中のユーザーアカウント削除ボタンを押すと、 `deleteAccount` メソッドにログインユーザーのオブジェクトデータを渡す。

```jsx
import { getAuth, deleteUser } from "https://www.gstatic.com/firebasejs/9.8.1/firebase-auth.js"

document.getElementById("user_delete_btn").addEventListener("click", deleteAccount);

const deleteAccount = function () {
	const auth = getAuth();
	//引数にログイン中のユーザーデータを渡す
	deleteUser(auth.currentUser).then(function () {
		//削除が成功したときの処理
	}).catch(function (error) {
		//削除が失敗したときの処理
	});
}
```

- 発生したエラー
ログイン状態が長すぎると、アカウント削除ができない場合があった。
再度ログインしてアカウント削除のメソッドを実行すると問題なく削除できた。

# エラーについて

> [Admin Authentication API エラー（公式）](https://firebase.google.com/docs/auth/admin/errors?hl=ja)

# 最後に

何か間違っている箇所などがありましたら、ご指摘くださると幸いです。

# 参考資料

- [スタートガイド（公式）](https://firebase.google.com/docs/auth/web/start?hl=ja)
- [Authenticationメソッド（公式）](https://firebase.google.com/docs/reference/js/auth)
- [Firebase でユーザーを管理する（公式）](https://firebase.google.com/docs/auth/web/manage-users?hl=ja)
- [【バージョン9】利用可能なFirebaseJSSDK（公式）](https://firebase.google.com/docs/web/learn-more?hl=ja#available-libraries)