LoginSignup
73
81

More than 3 years have passed since last update.

Next.js × TypeScript × Firebase AuthenticationでGoogle認証を実装する

Last updated at Posted at 2020-09-13

概要

Next.js × TypeScript × Firebase Authenticationを用いたgoogle認証機能を実装してみました。

実装(Firebase側)

プロジェクトを作成する

Firebaseにアクセスし、新しいプロジェクトを作成します。
作成が完了したら、『ウェブ』というアイコンをクリックし、アプリ名の登録を行います。

スクリーンショット 2020-09-13 15.00.41.png

スクリーンショット 2020-09-13 15.01.35.png

アプリ名の登録が完了すると、下記のようなスクリプトが表示されるかと思います。
こちらはnextアプリ側で使うので、コピーしておきます。

var firebaseConfig = {
    apiKey: xxxxx
    authDomain: xxxxx,
    databaseURL: xxxxx,
    projectId: xxxxx,
    storageBucket: xxxxx,
    messagingSenderId: xxxxx,
    appId: xxxxx,
    measurementId: xxxxx
};

Google認証を有効にする

Firebaseのコンソール画面のSign-in methodタブにあるログインプロバイダの中でGoogle認証を有効化・無効化する部分があるので、まずそちらで有効化します。

スクリーンショット 2020-09-13 14.56.05.png

これでFirebase側での設定は終了です。

実装(Next.js側)

インストール

firebase Authentication機能を利用したいので、
アプリケーションディレクトリにてfirebaseをインストールします。

myapp
$ yarn add firebase

必要ファイルを生成

.env

アプリケーションディレクトリにて.envを生成します。

myapp
$ touch .env
$ vim .env

.envにコピーしたスクリプトの値を記述していきます。
各個人、値が違うので適宜記述してください。

myapp/.env
FIREBASE_API_KEY=xxxxx
FIREBASE_AUTH_DOMAIN=xxxxx
FIREBASE_DATABASE_URL=xxxxx
FIREBASE_PROJECT_ID=xxxxx
FIREBASE_STORAGE_BUCKET=xxxxx
FIREBASE_MESSEGING_SENDER_ID=xxxxx
FIREBASE_APP_ID=xxxxx
FIREBASE_MEASUREMENT_ID=xxxxx

設定し終えたら、.gitignoreに.envがpushされないように追加を忘れないでください。

next.config.js

.envの値をnextアプリでも利用できるようにnext.config.jsに記述していきます。

myapp/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_MESSEGING_SENDER_ID: process.env.FIREBASE_MESSEGING_SENDER_ID,
    FIREBASE_APP_ID: process.env.FIREBASE_APP_ID,
    FIREBASE_MEASUREMENT_ID: process.env.FIREBASE_MEASUREMENT_ID,
  },
}

Firebase.ts

.envの値を利用し、Firebase.tsに設定を記述していきます。

myapp/src/utils/Firebase.ts

import firebase from 'firebase'

const config = {
  apiKey: process.env.FIREBASE_API_KEY,
  authDomain: process.env.FIREBASE_AUTH_DOMAIN,
  databeseURL: process.env.FIREBASE_DATABASE_URL,
  projectId: process.env.FIREBASE_PROJECT_ID,
  storageBucket: process.env.FIREBASE_STORAGE_BUCKET,
  messagingSenderId: process.env.FIREBASE_MESSEGING_SENDER_ID,
  appId: process.env.FIREBASE_APP_ID,
  measurementId: process.env.FIREBASE_MEASUREMENT_ID,
}
// firebase.appsをチェックし、ロードされているかどうかを確認。
// なければinitializeAppを実行
if (!firebase.apps.length) {
  firebase.initializeApp(config)
}

export default firebase

Auth.tsxでContextの作成

ユーザー情報の値をグローバルに持ち、バケツリレーを回避しつつ、Auth.tsx配下のコンポーネントたちに値が渡るようにContextの作成を行います。

src/context/Auth.tsx
import { User } from 'firebase';
import { FC, createContext, useEffect, useState } from 'react';

import firebase from '../utils/Firebase';

type AuthContextProps = {
  currentUser: User | null | undefined
}

const AuthContext = createContext<AuthContextProps>({ currentUser: undefined });

const AuthProvider: FC = ({ children }) => {
  const [currentUser, setCurrentUser] = useState<User | null | undefined>(
    undefined
  );

  useEffect(() => {
    // ログイン状態が変化するとfirebaseのauthメソッドを呼び出す
    firebase.auth().onAuthStateChanged((user) => {
      setCurrentUser(user);
    })
  }, []);

  /* 下階層のコンポーネントをラップする */
  return (
    <AuthContext.Provider value={{ currentUser: currentUser }}>
      {children}
    </AuthContext.Provider>
  )
}

export { AuthContext, AuthProvider }

_app.tsxにてComponentをAuthProviderでラップすることを忘れないでください。

src/pages/_app.tsx

import React, { useEffect } from 'react'
import { AppProps } from 'next/app'
import { AuthProvider } from '../context/Auth'

const MyApp = ({ Component, pageProps }: AppProps): JSX.Element => {
  return (
    ------
     <AuthProvider>
       <Component {...pageProps} />
     </AuthProvider>
    ------
  )
}

export default MyApp

サインイン画面

それでは実際にサインアップ画面の実装を行っていきます。
尚、今回はUI側の実装は簡易的なものになりますので、UI実装は適宜実装してください。

src/signIn.tsx
import { FC, useEffect, useContext } from 'react';
import Router from 'next/router';
import firebase from '../../utils/firebase';
import { AuthContext } from '../../context/Auth';

const SignIn: FC = () => {
  const { currentUser } = useContext(AuthContext);

  useEffect(() => {
    currentUser && Router.push('/')
  }, [currentUser]);

  const login = () => {
    const provider = new firebase.auth.GoogleAuthProvider();
    firebase.auth().signInWithRedirect(provider);
  }
  return (
     <div className="container">
      <button onClick={login}>googleでログインする</button>
     </div>
  )
}
  • useContextによって親よりすべての子たちがcurrentUserという現在ログインしているユーザー情報の値を利用できるようにしています。
    useStateと合わせて利用することでpropsによりバケツリレーを行うことなく、情報更新や値渡しが可能になり、複雑にならずに済むことがメリットです。

  • useEffectによってもし現在クライアントがログインしていた場合、ホーム画面へリダイレクトするようにしています。[currentUser]の部分はcurrentUserの値が変更された場合、useEffectが発火するようにしています。

動作確認

実装が完了したら、ホーム画面でcurrentUserのメールアドレスなどを表示させてみましょう。

参考リンク

73
81
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
73
81