22
19

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

VercelにホスティングしたNext.jsでFirebase Authenticationを使うベストプラクティス

Posted at

こんな人におすすめ

  • コンポーネントでログインを判別して表示を分けるには?
  • コードにAPI Keyとかベタガキしたくない、簡単な方法は?

今回、数時間ハマった。次回迷わないようにメモしておく。
もっといい方法あったら教えてください

コンポーネントまわり

参考:https://firebase.google.com/docs/auth/web/manage-users?hl=ja

pages/index.jsに以下を貼り付ける


import * as firebase from "firebase/app";
import "firebase/auth";
import { useState } from 'react'

const firebaseConfig = {
  apiKey: process.env.FIREBASE_API_KEY,
  authDomain: process.env.FIREBASE_AUTH_DOMAIN,
  databaseURL: process.env.FIREBASE_DATABASE_URL,
  projectId: process.env.FIREBASE_PROJECT_ID,
  storageBucket: process.env.FIREBASE_STORAGE_BUCKET,
  messagingSenderId: process.env.FIREBASE_MESSAGING_SENDER_ID,
  appId: process.env.FIREBASE_APP_ID,
  measurementId: process.env.FIREBASE_MEASUREMENT_ID
};
if (!firebase.apps.length) {
  firebase.initializeApp(firebaseConfig)
}

export default function SignInOut() {
  const [user, setUser] = useState(undefined)
  firebase.auth().onAuthStateChanged((user) => { user ? setUser(user) : setUser(undefined) });

  function signInWithTwitter() {
    const provider = new firebase.auth.TwitterAuthProvider();
    firebase.auth().signInWithPopup(provider).catch(function (error) {
      console.log(error.code, error.message)
    });
  }

  function signOut() {
    firebase.auth().signOut().catch(function (error) {
      console.log(error.code, error.message)
    })
  }

  function SignInOutButton() {
    return user ?
      <button onClick={signOut}>SignOut</button> :
      <button onClick={signInWithTwitter}>SignIn</button>

  }

  return <SignInOutButton />
}

簡単な解説

  • firebaseのドキュメントを読むと、onAuthStateChangedを使えとは書いてあるが、それをどう使えばログインを判別できるのかがわからなかった。
  • 結論、onAuthStateChangednの中でstateをsetする処理を書けばOKらしい。
  • コンポーネント側からはそのstateをみて、だし分けてやれば良い。
  • ログインとログアウトのhandleでstateをsetしてしまうと、コンポーネント側に反映されないので注意...

環境変数まわり

参考:https://nextjs.org/docs/basic-features/environment-variables

.env.localに環境変数を定義する

FIREBASE_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
FIREBASE_AUTH_DOMAIN=xxxxxxxxxxxxx.firebaseapp.com
FIREBASE_DATABASE_URL=https://xxxxxxxxxxxxx.firebaseio.com
FIREBASE_PROJECT_ID=xxxxxxxxxxxxx
FIREBASE_STORAGE_BUCKET=xxxxxxxxxxxxx.appspot.com
FIREBASE_MESSAGING_SENDER_ID=xxxxxxxxxxxxx
FIREBASE_APP_ID=1:xxxxxxxxxxxxx:web:xxxxxxxxxxxxxxxxxxx
FIREBASE_MEASUREMENT_ID=x-xxxxxxxxxxxxx

こいつをgitで管理してしまうと、わるい人にfirebaseアカウントを使われてしまうので、しっかりと.gitignoreに追加しておく

vercelで環境変数を定義する

GUIでぽちぽち入力していく
image.png

vercel CLI を使って、ここからローカルに環境変数をpullしてくる方法でも良いかも

next.config.jsに以下を貼り付ける

module.exports = {
    env: {
        FIREBASE_API_KEY: process.env.FIREBASE_API_KEY,
        FIREBASE_AUTH_DOMAIN: process.env.FIREBASE_AUTH_DOMAIN,
        FIREBASE_DATABASE_URL: process.env.FIREBASE_DATABASE_URL,
        FIREBASE_PROJECT_ID: process.env.FIREBASE_PROJECT_ID,
        FIREBASE_STORAGE_BUCKET: process.env.FIREBASE_STORAGE_BUCKET,
        FIREBASE_MESSAGING_SENDER_ID: process.env.FIREBASE_MESSAGING_SENDER_ID,
        FIREBASE_APP_ID: process.env.FIREBASE_APP_ID,
        FIREBASE_MEASUREMENT_ID: process.env.FIREBASE_MEASUREMENT_ID,
    }
}

その他

ローカルではログインログアウトが正常に動作していたのに、デプロイしたら動かない...

firebase Authentication の設定でvercelのドメインを許可

firebaseのコンソールから、Authentication > Sign-In Method > 承認済みドメイン と進んで、そこにvercelによってデプロイされたドメイン(xxx.vercel.app など)を追加する

コレを忘れると、開発者ツールのコンソールになんかエラーが出て、正常に処理されない。

22
19
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
19

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?