42
39

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.

Firebase Authenticationを利用する【Javascript、Vue.js】

Posted at

Firebaseとは

firebase.png

Firebaseは、Googleが提供するバックエンドサービスです。いわゆる、BaaS(Backend as a Service)です。
Firebaseは、バックエンドのサービスを担ってくれるので、開発者はアプリケーションの開発に専念することができ、バックエンドで動くサービスを作成、管理する必要はありません。
そのため、素早くアプリケーションをリリースるることができます。
Firebaseは、iOS/AndroidアプリからWebサービスまで幅広く使えます。

Firebaseには、以下のような様々な機能が提供されています。

  • Firebase Authentication
    アカウント機能を提供します。メールアドレスとパスワードを使用した一般的な認証の他に、電話番号、匿名認証、TwitterやGoogleアカウント、FacebookなどのSNS認証を使用できます。

  • Realtime Database
    オブジェクト型のNoSQLデータベースです。その名の通り、リアルタイムでクライアント全体の情報を同期することができます。データベースの状態を監視して変更があった場合、自動で更新してくれるので、簡単にチャット機能を実装することができます。

  • Cloud Firestore
    上記のRealtime Databaseの性能をさらに向上させた、新しいデータベースです。基本的に特別な事情がない限りこちらがおすすめされています。Realtime Databaseと異なり、データをドキュメントで保存します。

  • Cloud Storage
    写真や動画など、バイナリーデータを保存するストレージです。

  • Firebase Hosting
    HTML、CSS、JavaScriptで構成されたWebアプリケーションなど、静的なページを公開するためのホスティングサービスです。CDNを利用して、コンテンツを高速に配信することができます。

  • Firebase Analytics
    アプリの使用状況や、ユーザーの行動などを把握することができます。
    500以上のイベントに関するレポートを無制限に生成できます。

  • Firebase Crashlytics
    アプリケーションのクラッシュレポートを送信します。

これらの機能はFirebaseの提供するすべての機能のほんの一部にしかすぎません。すべての機能を知りたい場合には、ぜひ公式サイトを確認してみてください。

プロジェクトを作成する

実際にFirebaseのプロジェクトを作成します。Googleアカウントがない場合には先に作成しておく必要があります。

プロジェクトの追加

まずはFirebaseのコンソールへ移動します。
プロジェクトの作成をクリックしましょう。

スクリーンショット 20200412 21.45.15.png

適当にプロジェクトの名前を付けます。
スクリーンショット 20200412 21.47.39.png

いくつかの項目を聞かれるので(Google Analticsの使用の有無など)確認したら続行をクリックします。

以下のような画面になったらプロジェクトの作成は完了です。
スクリーンショット 20200412 21.48.28.png

Firebaseを利用するためのAPIキーを取得しましょう。今回はJavaScript使用するので、Webアプリケーションのアイコンをクリックします。

スクリーンショット 20200412 21.55.10.png

適当なアプリケーションの名前を付けましょう。
スクリーンショット 20200412 21.51.43.png

JavaSriptのコードが出てくるので、コピペして使用します。
スクリーンショット 20200412 21.52.12.png

これで基本的なFirebaseの設定は完了です。

Firebase Authentication

実際にFirebase Authenticationを試してみます。
ログイン認証に様々な方法が使えますが、今回はGoogleアカウントを用いた認証を行います。
理由はAPIキー等の入手の必要がなく、とても簡単だからです。(ちなみにTwitter APIはAPIの利用に審査が必要で、審査の申請を出すために利用理由を英語で200文字以上入力する必要があるなどかなり面倒です)

次のような簡単なログインボタンとログアウトボタンだけが表示されるHTMLファイルを用意しました。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <style>
    .hide {
      display: none;
    }
  </style>
  <title>Document</title>
</head>
<body>
  <button id="login">ログイン</button>
  <button id="logout" class="hide"></button>
  
  <script src="https://www.gstatic.com/firebasejs/7.14.0/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/7.14.0/firebase-auth.js"></script>

  <script>
    // Your web app's Firebase configuration
    var firebaseConfig = {
      apiKey: "AIzaSyDPOIelluKaZv8--wAksjl9CZrrOdqYJ40",
      authDomain: "awesome-wares-264812.firebaseapp.com",
      databaseURL: "https://awesome-wares-264812.firebaseio.com",
      projectId: "awesome-wares-264812",
      storageBucket: "awesome-wares-264812.appspot.com",
      messagingSenderId: "850229978924",
      appId: "1:850229978924:web:8c88bd3497c24449766e89"
    };
    // Initialize Firebase
    firebase.initializeApp(firebaseConfig);
  </script>
  <script src="./firebase.js"></script>
</body>
</html>

これをもとにfirebase.jsにコーディングしていきましょう。

Googleプロバイダオブジェクトのインスタンスを作成

Firebase Authentication機能を利用するためには、基本的にはfirebase.auth()の名前空間で作業をします。
auth用のCDNも忘れずにfirebase-app.jsの後に読み込むようにします。
<script src="https://www.gstatic.com/firebasejs/7.14.0/firebase-auth.js"></script>
Firebase Auth 自体は多くのサービスプロバイダのOAuthのラッパーとなっています。
Googleアカウントを利用するので、Googleサービスプロバイダを呼び出しましょう。

const provider = new firebase.auth.GoogleAuthProvider()

ログインボタンがクリックされたときに認証を行う

早速認証を行いましょう。ログインボタンが押されたときに認証がされるようにしたいので、ログインボタンのDOMを取得してclickイベントを購読しましょう。

const loginBtn = document.getElementById('login')

loginBtn.addEventListener('click', () => {
  // この中に認証コードを書く
})

認証するさいには、ポップアップウィンドウを表示するか、ログインページにリダイレクトするか選択できます。

  • ポップアップでログイン
    signInWithPopupを呼び出す。

  • ログインページにリダイレクトでログイン
    signInWithRedirectを呼び出す。

今回はポップアップをでログインをしましょう。以下のように呼び出します。

loginBtn.addEventListener('click', () => {
  firebase.auth().signInWithPopup(provider).then(result => {
    // GoogleプロパイダのOAuthトークンを取得します。
    const token = result.credential.accessToken
    // ログインしたユーザーの情報を取得します。
    const user = result.user
  }).catch(function(err) {
    console.error(err)
    // エラー処理
  })
})

ここまでできたら早速ログインボタンをクリックしてみましょう!

認証方法をプロジェクトで有効化する

おっと!エラーが発生してしまいました!コンソールには次のように書いてあります。
スクリーンショット 20200412 23.08.41.png

この認証方法は使えない、みたいなことが書いてあります。
そうです、うっかりしてましたFirebase Authenticationによる認証を利用するにはコンソールから利用する認証方法を有効化する必要があります。一度コンソールへ戻りましょう。

左のメニューバーから「Authentication」を選択します。
次に、上のタブから「Sign-in method」を選択しましょう。
プロパイダの一覧から「Google」を選択します。

スクリーンショット 20200412 23.14.18.png

右上にある「有効にする」をオンにします。
さらに、プロジェクトのサポートメールを選択してください。
オンになっていることが確認できたら「保存する」をクリックしましょう。

スクリーンショット 20200412 23.17.37.png

これで、Googleプロパイダが有効になりました。

スクリーンショット 20200412 23.20.52.png

もう一度ログインボタンをクリックしてみましょう。
Googleアカウントの選択画面がでてきて、ログインができるはずです。

現在ログインしているユーザーを取得する

通常、ログイン機能が必要なアプリケーションの場合、ユーザーが現在ログインしているかどうか、またログインしているユーザーの情報を知りたいはずです。

そのような場合、Authオブジェクトでオブザーバーを設定します。

firebase.auth().onAuthStateChanged(user => {
  if (user) {
    // ユーザーがログインしています。
  } else {
    // ユーザーはログインしていません。
  }
})

onAuthStateChangedはユーザーのログイン状態を監視します。
どうやらログイン情報はIndexedDBに保存されているようです。
firebase.auth().onAuthStateChangedはどうやってログイン中であることを判定しているんでしょうか?

firebase.auth().currentUserでも現在ログインしているユーザーが取得できるみたいですが、ログインしているはずなのにcurrentUsernullになることがあるのでおすすめはしません。

ユーザーインスタンスからはユーザーの情報が取得できます。

// uid
user.uid

// 名前
user.displayName

// プロフィール画像
user.photoURL

// メール
user.email

// 認証済みのメールアドレス化
user.emailVerified

// 電話番号
user.phoneNumber

// 匿名認証かどうか
user.isAnonymous

さらに、ユーザープロフィールなど、これ以上のユーザーの情報をもたせたいと思うかもしれません。
そのような場合には、Realtime DBCloud Firestoreを利用します。
userコレクションを作成して、uidをキーにドキュメントを追加すれば、ログインユーザーのさらなる情報を取得することができます。

ログアウト

ログインしたなら当然ログアウトもしたはずです。
ログアウトはsingOutを呼び出すだけです。

const logoutBtn = document.getElementById('logout')

logoutBtn.addEventListener('click', () => {
  firebase.auth().signOut().then(() => {
    // 成功
  }).catch(err => {
    // 失敗
  })
})

以上のように、普通に実装したらまあまあめんどくさい認証機能も簡単に実装することができました。

メールアドレスとパスワードによる認証

Firebase Authenticationによる、Googleアカウントでのログインについて取り上げました。次に、メールアドレスとパスワードによるログインについて取り上げます。

メールアドレスとパスワードによる認証を有効にする。

まずはじめに、前回同様認証を利用するには、その認証方法をコンソール上で有効にする必要があります。メール/パスワードプロパイダを有効にします。

スクリーンショット 20200419 17.20.55.png

スクリーンショット 20200419 17.24.05.png

メール/パスワードプロパイダを有効にすると、コンソール上でユーザーを追加することができます。

Usersタグをクリックしてユーザーを追加ボタンをクリックします。

スクリーンショット 20200419 17.25.08.png

適当なメールアドレスとパスワードを入力して、ユーザーを追加ボタンをクリックします。
ユーザーの一意となるUIDが付与され、今後このユーザーを利用してログインができるようになります。

ログインフォームを構築する。

予め用意されたUIを利用する

ログインフォームには、Firebaseに予め用意されているUIを利用することができます。
UIを利用するためには追加で以下のCDNを読み込みます。

<script src="https://cdn.firebase.com/libs/firebaseui/3.5.2/firebaseui.js"></script>
<link type="text/css" rel="stylesheet" href="https://cdn.firebase.com/libs/firebaseui/3.5.2/firebaseui.css" />

jsファイルに、次のようにUIを初期化するコードを書きます。
ログイン方法には、メールアドレスとパスワードによる認証を指定します。

const ui = new firebaseui.auth.AuthUI(firebase.auth());
ui.start('#firebaseui-auth-container', {
  signInOptions: [
    firebase.auth.EmailAuthProvider.PROVIDER_ID
  ],
  // Other config options...
})

ログインウィジェットがレンダリングされるDOMを用意します。ui.startの第一引数に指定されているセレクターに描画されます。(この例では#firebaseui-auth-container

最終的なHTMLは次のようになります。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <script src="https://www.gstatic.com/firebasejs/7.14.0/firebase-app.js"></script>
  <script src="https://www.gstatic.com/firebasejs/7.14.0/firebase-auth.js"></script>
  <script src="https://cdn.firebase.com/libs/firebaseui/3.5.2/firebaseui.js"></script>
  <link type="text/css" rel="stylesheet" href="https://cdn.firebase.com/libs/firebaseui/3.5.2/firebaseui.css" />  
  <title>Firebase Auth</title>
</head>
<body>
  <div id="firebaseui-auth-container"></div>
  <script>
    // Your web app's Firebase configuration
    var firebaseConfig = {
      apiKey: "AIzaSyDPOIelluKaZv8--wAksjl9CZrrOdqYJ40",
      authDomain: "awesome-wares-264812.firebaseapp.com",
      databaseURL: "https://awesome-wares-264812.firebaseio.com",
      projectId: "awesome-wares-264812",
      storageBucket: "awesome-wares-264812.appspot.com",
      messagingSenderId: "850229978924",
      appId: "1:850229978924:web:8c88bd3497c24449766e89"
    };
    // Initialize Firebase
    firebase.initializeApp(firebaseConfig);
    // const provider = new firebase.auth.GoogleAuthProvider()
  </script>
  <script src="./firebase.js"></script>
</body>
</html>

次のようなログイン画面が表示されました。
さきほど作成したユーザーのメールアドレスを入力してみましょう。

スクリーンショット 20200419 18.08.34.png

このままパスワードを入力すれば、ログインが完了します。
(ログイン後の処理を書いていないため、とくになにもおきませんが)
スクリーンショット 20200419 18.11.08.png

また、存在しないユーザーのメールアドレスを入力した場合、そのまま新しいユーザーを作成することができます。

スクリーンショット 20200419 18.13.15.png

独自のUIコンポーネントを利用する

FirebaseのUIを利用して、簡単にログイン機能を利用することができました。
しかし、独自のUIコンポーネントを利用したいことでしょう。
また、ここからはVue.jsを利用したWebアプリケーションを例にして説明していきます。(すでに作ったものを利用したいので)

Vue CLIアプリ作成

いつもどおりVue CLIによりVueアプリを作成します。

vue create firebase-app

どうせ使うのでRouterVuexも入れておきましょう。

? Please pick a preset: 
  default (babel, eslint) 
❯ Manually select features
? Check the features needed for your project: 
 ◉ Babel
 ◯ TypeScript
 ◯ Progressive Web App (PWA) Support
 ◉ Router
❯◉ Vuex
 ◯ CSS Pre-processors
 ◉ Linter / Formatter
 ◯ Unit Testing
 ◯ E2E Testing

firebase初期化

FireStoreモジュールをnpmでインストールします。

npm install firebase

src/plugins/firebase.jsファイルを作成して初期化コードを作成して、export defautしてアプリケーションでfirebaseを利用できるようにします。

import firebase from 'firebase'

if (!firebase.apps.length) {
  firebase.initializeApp(
    {
      apiKey: process.env.VUE_APP_APIKEY,
      authDomain: process.env.VUE_APP_AUTHDOMAIN,
      databaseURL: process.env.VUE_APP_DATABASEURL,
      projectId: process.env.VUE_APP_PROJECTID,
      storageBucket: process.env.VUE_APP_STORAGEBUCKET,
      messagingSenderId: process.env.VUE_APP_MESSAGINGSENDERID,
      appId: process.env.VUE_APP_APPID,
      measurementId: process.env.VUE_APP_MEASUREMENTID,
    }
  )
}

export default firebase

APIキーはクライアントアプリケーションで利用される前提なので、そのまま書いても構いませんが、なんとなく.env.localから読み込みます。

.env.local
VUE_APP_APIKEY=MY_API_KEY
VUE_APP_AUTHDOMAIN=MY_AUTHDOMAIN
VUE_APP_DATABASEURL=MY_DATABASEURL
VUE_APP_PROJECTID=MY_PROJECT_ID
VUE_APP_STORAGEBUCKET=MY_STORAGE
VUE_APP_MESSAGINGSENDERID=MY_MESSAGER
VUE_APP_APPID=MY_APPID
VUE_APP_MEASUREMENTID=MY_MEMEASUREMENTID

Firebaseの認証機能を提供するモジュールをsrc/plugins/auth.jsに書きましょう。

import firebase from '@/plugins/firebase'

export function login (email, password) {
   return firebase.auth().signInWithEmailAndPassword(email, password)
}

export function logout() {
  return firebase.auth().signOut()
}

export function reAuth(email, password) {
  return firebase.auth.EmailAuthProvider.credential(email, password)
}

export function auth () {
  return new Promise(resolve => {
    firebase.auth().onAuthStateChanged(user => {
      resolve(user || false)
    })
  })
}

メールアドレスとパスワードによるログインを利用するには、firebase.auth().signInWithEmailAndPasswordを利用するので、これをラップした関数をexportします。

ログアウトは前回と同じく、firebase.auth().signOutを利用します。これもラップします。
reAuth関数は後ほど使用します。

ログイン画面

ここからコピペしたログインフォームをちょっといじって利用します。

こんな感じです。
スクリーンショット 20200419 19.01.43.png
スクリプト部分このようになっています。
なお、バリデーションやエラー処理などは省いています。


<script>
import { validationMixin } from 'vuelidate'
import { required, email } from 'vuelidate/lib/validators'
import { login } from '@/plugins/auth'

export default {
  data() {
    return {
      email: '',
      password: '',
      redirect: '' // ログイン後にリダイレクトさせたいurl
    }
  },
  // Vuelidateによるバリデーション
  mixins: [validationMixin],
  validations: {
    email: { required, email },
    password: { required },
  },
  methods: {
    onSubmit () {
      this.$v.$touch(
      if (this.$v.$invalid) return
      login(this.email, this.password)
        .then(() => this.$router.push(this.redirect))
        .catch(() => {
          // エラー処理をここで行う
        })
    },
  },
}
</script>

はじめにインポートしている

import { validationMixin } from 'vuelidate'
import { required, email } from 'vuelidate/lib/validators'

これらは、Vuelidateという軽量バリデーションライブラリです。ここでは詳細は割愛します。

また、先程作成したauthモジュールからlogin関数をインポートしましょう。

import { login } from '@/plugins/auth'

dataプロパティのemailpasswordv-modelによってフォーム入力とバインディングされます。

methodsプロパティのonSubmitメソッドは、submitイベントによって呼び出されます。

バリデーションが通過したなら、login関数を呼び出しましょう。
先程見たとおり、login関数はfirebase.auth().signInWithEmailAndPasswordのラッパー関数です。
firebase.auth().signInWithEmailAndPasswordは、メールアドレスとパスワードを渡すこによって、ログインをすることができます。

firebase.auth().signInWithEmailAndPasswordは、Promiseを返すので、ログインが成功していることを確認できたなら、ログイン後リダイレクトをさせます。

なんらかの理由でログインに失敗しているのなら、(メールアドレスかパスワードが間違っている、ネットワークエラーなど)エラーをキャッチしてエラー処理を行います。

ログインユーザーの取得

現在ログインしているユーザーは、先週と同じくfirebase.auth().onAuthStateChangedで取得します。
これも、authモジュールauth関数によってPromiseを返すようにラップしています。

ユーザープロフィールを取得できます。

import { auth } from `@/plugins/auth`

async () => {
  const user = await auth()
  if (!user) return 
  user.displayName
  user.email
  user.emailVarified
  user.photoURL
  user.uid 
}

ユーザーのプロフィールを更新する

updateProfileメソッドを利用すれば、ユーザーのプロフィールを更新することができます。

import { auth } from `@/plugins/auth`

async () => {
  const user = await auth()
  if (!user) return 
  user.updateProfile({
    displayName: '新しい名前',
    photoURL: 'newPhoto.jpg'
  })
}

メールアドレスを更新する

ユーザーのメールアドレスを更新するには、updateEmailを利用します。
注意しなければいけないところは、メールアドレスやパスワードの更新など、セキュリティ上重要な操作はユーザーが再認証する必要があるところです。

再認証をするためには、まずは新しい認証情報を取得します。

そのためには、firebase.auth.EmailAuthProvider.credentialemailpasswordを渡します。
取得した認証情報をuserメソッドのreauthenticateWithCredentialにわたすことで、再認証が完了します。

これはauthモジュールreAuth関数でラップしてるので、次のように新しい認証情報を取得できます。


import { reAuth } from '@/src/plugins/auth'

export default {
methods: {
  async onSubmit() {
      try {
        this.loading = true
     // 再認証のためのメールアドレスは、ログインユーザーから取得します。
     // パスワードはフォーム入力から取得します。
        const credential = await reAuth(this.user.email, this.password)
        await this.user.reauthenticateWithCredential(credential)
        await this.user.updateEmail(this.email)
     } catch {
       // エラー処理
     } finally { 
       this.loading = false
     }
  }
}

ユーザーのパスワードを更新する

パスワードの更新も、同じく再認証をする必要があります。
userメソッドのupdatePasswordを利用します。

まとめ

Firebaseのプロジェクトの初期化から、認証機能の実装までを取り上げました。
思っていたよりも簡単に実装でき、日本語のドキュメントも充実しているので素晴らしいですね。
個人で素早く開発をしたいときにとても役立つと思います。

参考

ドキュメント

42
39
0

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
42
39

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?