Google先生のアカウントをもっていない人なんてめったにいない。 Googleの認証ができれば新規の会員登録の障壁がへる。この機能は今後のWEBアプリの基本となると思うのでできてよかった。
この記事はReact Firebase入門シリーズです
1-1-1・ Firebase初期設定とFirebaseAuthのSignUp
1-1-2・ 「react-hook-form」を入れてみた
1-1-3・ AuthのSignUpの通信エラー対応
1-2 ・ FirebaseAuthのログイン処理
1-3 ・ FirebaseAuthのログイン認証とログアウト処理
1-4 ・ FirebaseAuthのパスワード初期化処理
1-5 ・ FirebaseAuthのメールアドレスの有効化
1-6 ・ FirebaseAuthのメールアドレスとパスワード変更
1-7 ・ FirebaseAuthの表示名変更
1-8 ・ FirebaseAuthの拡張項目追加
1-9-1 ・ FirebaseAuthのTwitter認証
1-9-2 ・ FirebaseAuthのTwitter認証(既存ユーザー向け)と解除
1-10 ・ FirebaseAuthのGoogle認証(既存ユーザー含む)と解除 今ここ
2-1・ FirebaseStorageのファイルアップ:基礎
2-2・ FirebaseStorageのファイルアップ前に画像の切り抜き
2-3・ FirebaseStorageのファイルアップの移動
3-1・FirestoreのCRUD
3-2・Firestoreのデータ取得補足
3-3・Firestoreのページネーション処理
3-4・Firestoreのコレクション(テーブル)のJOIN
やりたい事
事前作業
FirebaseのAuthGoogleのプロバイダーを有効化します
FirebaseのWebコンソールへログインしたら、メニュー「Authentication」→「Sign-in method」→「Google」→「編集」とたどります。
有効化にする
これだけです。Twitterと違い簡単です。
プログラムについて
Googleの認証のプロバイダーを追加する。Twitterとそこまで変わらない /src/firebase.js
export const Twitter = new firebase.auth.TwitterAuthProvider();
+ export const Google = new firebase.auth.GoogleAuthProvider();
export default firebase;
Twitterと同様にコンポーネントを作ります。ほぼ同じなのですが、もしかしてOAuthのスコープを指定する事があるかもしれないので分けて作りました
/src/firebaseprovider/Google.js
iimport React, { useState, useEffect } from "react"; import { useAuth } from "../../contexts/AuthContext" import firebase, {Google} from "../../firebase" import { useHistory} from "react-router-dom" import { Button,} from '@material-ui/core'; import { createStyles, makeStyles, Theme } from "@material-ui/core/styles"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faGoogle } from "@fortawesome/free-brands-svg-icons"; const useStyles = makeStyles((theme: Theme) => createStyles({ googleBtn: { flexGrow: 1 }, googleloginBtn: { marginTop: theme.spacing(2), flexGrow: 1 }, googleIcon: { fontSize: "1.5rem", }, }) ); export const GoogleSingUpLogin = (props) => { const classes = useStyles();//Material-ui const history = useHistory() const [googleMessage, setGoogleMessage] = useState("") async function handleGoogleSignup (event) { console.log("handleGoogleSignup") Google.setCustomParameters({ prompt: 'select_account', // 追加 }); setGoogleMessage("認証中") firebase .auth() .signInWithPopup(Google) .then((result) => { console.log(result); setGoogleMessage("認証に成功しました。ダッシュボードにリダレクトします") setTimeout(function(){ console.log("リダレクト処理") history.push("/dashboard") },1000); }).catch(function(error) { switch (error.code) { case "auth/network-request-failed": setGoogleMessage("通信がエラーになったのか、またはタイムアウトになりました。通信環境がいい所で再度やり直してください。"); break; case "auth/credential-already-in-use": setGoogleMessage("他のユーザーでGoogle認証しているため、認証ができませんでした。"); break; case "auth/user-disabled": setGoogleMessage("入力されたアカウントまたはメールアドレスは無効(BAN)になっています。"); break; case "auth/requires-recent-login": setGoogleMessage("別の端末でログインしているか、セッションが切れたので再度、ログインしてください。(ログインページにリダイレクトします)"); setTimeout(function(){ console.log("リダレクト処理") history.push("/login") },3000); break; default: //想定外 setGoogleMessage("失敗しました。通信環境がいい所で再度やり直してください。"); } }); } return ( <> {googleMessage && <div style={{ color: "red" }}>{googleMessage}</div>} <Button fullWidth variant="contained" size="large" color="primary" className={classes.googleloginBtn} onClick={handleGoogleSignup} > <FontAwesomeIcon className={classes.googleIcon} icon={faGoogle} />{props.title} </Button> </> ) } export const GoogleLink = () => { const classes = useStyles();//Material-ui const [isGoogleLink, setIsGoogleLink] = useState(false) const [googleMessage, setGoogleMessage] = useState("") const { currentUser, } = useAuth() const history = useHistory() useEffect(() => { async function fetchData() { //providerData Linkチェック setIsGoogleLink(false) currentUser.providerData.forEach(element => { if (element.providerId === "google.com" ){ setIsGoogleLink(true) } }); } fetchData(); },[currentUser]); function handleGoogleUnLink () { console.log("handleGoogleUnLink") setGoogleMessage("") currentUser.unlink("google.com").then(function() { setGoogleMessage("Googleとのリンクを解除しました") setIsGoogleLink(false) }).catch(function(error) { console.log(error) switch (error.code) { case "auth/network-request-failed": setGoogleMessage("通信がエラーになったのか、またはタイムアウトになりました。通信環境がいい所で再度やり直してください。"); break; case "auth/credential-already-in-use": setGoogleMessage("他のユーザーでGoogle認証しているため、認証ができませんでした。"); break; case "auth/requires-recent-login": setGoogleMessage("別の端末でログインしているか、セッションが切れたので再度、ログインしてください。(ログインページにリダイレクトします)"); setTimeout(function(){ console.log("リダレクト処理") history.push("/login") },3000); break; default: //想定外 setGoogleMessage("失敗しました。通信環境がいい所で再度やり直してください。"); } }); } async function handleGoogleLinkWithPopup (event) { console.log("handleGoogleLinkWithPopup") setGoogleMessage("") Google.setCustomParameters({ prompt: 'select_account', // 追加 }); currentUser.linkWithPopup(Google).then(function(result) { console.log("handleGoogleLinkWithPopup:result",result) setGoogleMessage("Googleとリンクしました") setIsGoogleLink(true) }).catch(function(error) { // Handle Errors here. switch (error.code) { case "auth/network-request-failed": setGoogleMessage("通信がエラーになったのか、またはタイムアウトになりました。通信環境がいい所で再度やり直してください。"); break; case "auth/credential-already-in-use": setGoogleMessage("他のユーザーでGoogle認証しているため、認証ができませんでした。"); break; case "auth/requires-recent-login": setGoogleMessage("別の端末でログインしているか、セッションが切れたので再度、ログインしてください。(ログインページにリダイレクトします)"); setTimeout(function(){ console.log("リダレクト処理") history.push("/login") },3000); break; default: //想定外 setGoogleMessage("失敗しました。通信環境がいい所で再度やり直してください。"); } console.log(error) // ... }); } return ( <> {googleMessage && <div style={{ color: "red" }}>{googleMessage}</div>} {isGoogleLink && <> <FontAwesomeIcon className={classes.googleIcon} icon={faGoogle} />Google:{' '}{' '}{' '}認証されています <Button fullWidth variant="contained" size="large" color="primary" className={classes.googleBtn} onClick={handleGoogleUnLink} > 認証を解除する </Button> </> } {!isGoogleLink && <> <FontAwesomeIcon className={classes.googleIcon} icon={faGoogle} />Google:{' '}{' '}{' '}認証されていません <Button fullWidth variant="contained" size="large" color="primary" className={classes.googleBtn} onClick={handleGoogleLinkWithPopup} > 認証する </Button> </> } </> ) }
あとはSignUPやログイン、プロフィール画面からコンポーネントを読んでいるだけです
SignUp
/src/Signup.js
<TwitterSingUpLogin title="Twitterでアカウント作成"/> + <GoogleSingUpLogin title="Googleでアカウント作成"/>
ログイン
/src/Login.js
<TwitterSingUpLogin title="TwitterでLoginする"/> + <GoogleSingUpLogin title="GoogleでLoginする"/>
プロフィール画面
/src/UpdateProfile.js
<Typography className={classes.subtitle2} variant="subtitle2"> 外部アプリケーション認証</Typography> <TwitterLink /> + <GoogleLink />
結果
結果詳細
- ログインが複数選ぶ事ができる。Twitterではできなかったんですが、Googleだとできるみたい。理由がわからないけど・・・
- Google認証で取得されたメールアドレスは有効化されていた
- アバターもGoogleに登録されている画像URLが設定されていた
- パスワードは設定されていなかった。パスワードを入力するとFirebaseのコンソールでメールのアイコンが追加された。
プロバイダーはpasswordだった・・・
できていない事
- OAuthのスコープを変更できるだけど。。。よくわからず・・・今の所は使わないので放置
省略可: 認証プロバイダにリクエストする追加の OAuth 2.0 スコープを指定します。スコープを追加するには、addScope を呼び出します。次に例を示します。
provider.addScope('https://www.googleapis.com/auth/contacts.readonly'); https://developers.google.com/identity/protocols/oauth2/scopes