チャットApp(認証機能)

前回ビュー部分を作ったので今回は、実際にfirebaseにユーザー登録し認証できるようにします。

関数の作成

functionsディレクトリにauth.tsを作って認証系の関数を作っていきます。

auth.ts

import FB, { googleProvider, twitterProvider } from "./firebase";
/**
* メールアドレス、パスワードを使用したユーザ登録
* 成功したらtrue, 失敗したらfalseを返す。
* @param email 
* @param password 
*/
export const signupUser = async(email:string, password:string):Promise<boolean> => {
   console.log(FB);
   const bool:boolean = await FB.createUserWithEmailAndPassword(email, password)
   .then(() => {
       return true;
   })
   .catch(error => {
       console.log(error);
       return false;
   });
   return bool;
}
/**
* メールアドレス、パスワードを使用したユーザログイン
* 成功したらtrue, 失敗したらfalseを返す。
* @param email 
* @param password 
*/
export const signinUser = async(email:string, password:string):Promise<boolean> => {
   const bool:boolean = await FB.signInWithEmailAndPassword(email, password)
   .then(() => {
       return true;
   })
   .catch(error => {
       console.log(error);
       return false;
   });
   return bool;
}
/**
* ユーザの匿名認証
* 成功したらtrue, 失敗したらfalseを返す。
*/
export const signinAnonymous = async():Promise<boolean> => {
   const bool:boolean = await FB.signInAnonymously()
   .then(() => {
       return true;
   })
   .catch(error => {
       console.log(error);
       return false;
   });
   return bool;
}
/**
* グーグルアカウントを使用した認証
* 成功したらtrue, 失敗したらfalseを返す。
*/
export const signinWithGoogle = async():Promise<boolean> => {
   const bool:boolean = await FB.signInWithPopup(googleProvider)
   .then(() => {
       return true;
   })
   .catch(error => {
       console.log(error);
       return false;
   });
   return bool;
}
/**
* ツイッターアカウントを使用した認証
* 成功したらtrue, 失敗したらfalseを返す。
*/
export const signinWithTwitter = async():Promise<boolean> => {
   const bool:boolean = await FB.signInWithPopup(twitterProvider)
   .then(() => {
       return true;
   })
   .catch(error => {
       console.log(error);
       return false;
   });
   return bool;
}
/**
* ログアウト処理
* 成功したらtrue, 失敗したらfalseを返す。
*/
export const signout = async():Promise<boolean> => {
   const bool:boolean = await FB.signOut()
   .then(() => {
       return true;
   })
   .catch(error => {
       return false;
   });
   return bool;
}
/**
* ユーザのログイン状態を確認する
* ログイン状態ならtrue, ログインしていないならfalseを返す。
*/
export const activeUserExist = ():boolean => {
   let bool:boolean;
   FB.onAuthStateChanged((user) => {
       if (user) {
           bool = true;
       } else {
           bool = false;
       }
   });
   return bool;
}

各関数の説明はコメントアウトにも書いているので割愛します。またそれに合わせて、firebase.tsにも不具合があったので少し修正を加えます。

firebase.ts

import firebase from "firebase";
import "firebase/auth";
import "firebase/firestore";
let FB:any;
export let FBdb:firebase.firestore.Firestore;
export let FBstorage:firebase.storage.Storage;
export let googleProvider:firebase.auth.GoogleAuthProvider;
export let twitterProvider:firebase.auth.TwitterAuthProvider;
try {
   const firebaseConfig = {
       apiKey:            process.env.FB_API_KEY,
       authDomain:        process.env.FB_AUTH_DOMAIN,
       databaseURL:       process.env.FB_DATABASE_URL,
       projectId:         process.env.FB_PROJECT_ID,
       storageBucket:     process.env.FB_STORAGE_BUCKET,
       messagingSenderId: process.env.FB_MESSAGING_SENDER_ID,
       appId:             process.env.FB_APP_ID,
       measurementId:     process.env.FB_MEASUREMENT_ID,
   };
   
   firebase.initializeApp(firebaseConfig);
   
   firebase.auth().setPersistence(firebase.auth.Auth.Persistence.LOCAL);
   
   FBdb            = firebase.firestore();
   FBstorage       = firebase.storage();
   googleProvider  = new firebase.auth.GoogleAuthProvider();
   twitterProvider = new firebase.auth.TwitterAuthProvider();
   FB              = firebase.auth();
   console.log("firebase init!");
} catch (error) {
   console.log(error);
}
export default FB;

変数FBを最後にエクスポートしないと各関数で読み込んだ時にundefinedになってしまいます。

ページに認証機能を実装する

上で定義した関数を読み込んで機能を実装していきます。全部載せると大量になってしまうので、追加・変更部分だけを掲載します。詳しくはgithubのページを最後に載せるのでそちらを確認してください。

signup.tsx

const handleSignup = async() => {
       setDisable(true);
       if (emailMessage[0] === "OK!!" && passwordMessage[0] === "OK!!") {
           const bool:boolean = await signupUser(email, password);
           if (bool) {
               console.log("successfully!");
           } else {
               console.log("failed.");
           }
           setDisable(false);
       } else {
           alert("メールアドレス・パスワードを入力してください。");
           setDisable(false);
       }
   }
   
   // 省略
 
               <BasicButton
                           fullWidth ={ true }
                           disabled  ={ disable }
                           onclick   ={ handleSignup }
                       >
                           登録
                       </BasicButton>

ここではまだ認証後のページ遷移等出来ないので、認証が成功したかどうかでコンソールのメッセージを表示するようにしています。

signin.tsx

const handleSignin = async() => {
       setDisable(true);
       if (emailMessage[0] === "OK!!" && passwordMessage[0] === "OK!!") {
           const bool:boolean = await signinUser(email, password);
           if (bool) {
               console.log("successfully!");
           } else {
               console.log("failed.");
           }
           setDisable(false);
       } else {
           alert("メールアドレス・パスワードを入力してください。");
           setDisable(false);
       }
   }
   
   const handleSigninWithGoogle = async() => {
       setDisable(true);
       const bool:boolean = await signinWithGoogle();
       if (bool) {
           console.log("successfully!");
       } else {
           console.log("failed.");
       }
       setDisable(false);
   }
   const handleSigninWithTwitter = async() => {
       setDisable(true);
       const bool:boolean = await signinWithTwitter();
       if (bool) {
           console.log("successfully!");
       } else {
           console.log("failed.");
       }
       setDisable(false);
   }
   const handleSigninAnonymous = async() => {
       setDisable(true);
       const bool:boolean = await signinAnonymous();
       if (bool) {
           console.log("successfully!");
       } else {
           console.log("failed.");
       }
       setDisable(false);
   }

signin.tsxも同様です。

これらを開発環境で実際使ってみると、firebaseのコンソールからちゃんと登録出来ていることが確認出来ます。

スクリーンショット 2020-08-16 12.41.07

あとは少し修正を加えてデプロイします。vercelのプレビュー機能で確認します。

スクリーンショット 2020-08-16 13.50.59

スクリーンショット 2020-08-16 13.51.05

ルートページでボタンをホバーした時に説明を表示する機能を付けてます。これで「グーグルのアカウント使いたいんだけどどっちのボタンだろう?」と悩まなくて良いですね。

また、スマホでの挙動を確かめられるのも良いですね。デベロッパーツールだけだとどうしても挙動を再現出来ない部分があるので助かります。

画像4

これまでのコードは以下で確認出来ます。
github

次回からプロフィールページとチャットルームの作成機能をやっていきます。

この記事が気に入ったらサポートをしてみませんか?