Firebase Authentication で LINE ログイン

公開日:

Firebase Authentication に LINE ログインを追加する方法です。

Firebase Authentication には様々なソーシャルログインがデフォルトで追加できるようになっていますが、LINE はデフォルトでは追加できません。

ですが、Firebase は Open ID Connect (OIDC) に対応しているカスタムプロバイダを追加できます。LINE ログインは Open ID Connect をサポートしているので、カスタムプロバイダとして LINE ログインを Firebase に追加してみます。

この記事ではポイントとなる部分を、かいつまんで書いていきます。詳細については参考リンクから確認して下さい。

やりかた

  1. Firebase Authentication を Identity Platform にアップグレード
  2. LINE Developers でログインチャンネルを作成
  3. Firebase に OIDC プロバイダ(OpenID Connect プロバイダ)の設定を入力
  4. LINE ログイン処理を実装

Firebase Authentication を Identity Platform にアップグレード

まずは Firebae Authentication を Firebase Authentication with Identity Platform にアップグレードします。

Identity Platform にアップグレードすることで OpenID Connect に対応される。

コードを追加すると、多要素認証、ブロッキング関数、SAML プロバイダや OpenID Connect プロバイダ向けサポートを追加できます。

Firebase Authentication

アップグレードの方法は以下のリンクから確認できます。

Firebase Authentication

[Identity Platform と Firebase Authentication の違い | Identity Platform Documentation | Google Cloud](https://cloud.google.com/identity-platform/docs/product-comparison?hl=ja

LINE Developers でチャンネルを作成

次に LINE 側の開発者向け管理コンソールである LINE Developers の設定をします。

LINE Developers の登録が済んでない人はまず LINE Developers に登録して下さい。

登録が済んだら LINE ログイン用のチャネルを作ります。この時チャネルのタイプはLINE ログインにして下さい。LINE ミニアプリだとこの後設定するコールバック URL が設定できないので LINE ログインを実装できません。

チャネルを作成する | LINE Developers

チャネルを作ったらコールバック URL を設定します。

コールバックURLを設定する | ウェブアプリにLINEログインを組み込む | LINE Developers

Firebase に OIDC プロバイダ(OpenID Connect プロバイダ)の設定を入力

Firebase に戻ってきて LINE Developers のチャネルの情報をなどを入力します。

LINE Developers で以下の情報をとってきて、Firebase に入力して下さい。

  • クライアント ID: チャンネル ID
  • クライアントシークレット: チャンネルシークレット

発行元はhttps://access.line.meにする。名前は任意です。今回、私はlineにしました。

ウェブアプリで OpenID Connect を使用して認証する | Firebase

LINE ログイン処理を実装

TypeScript(JavaScript) の実装です。私は Vue(Nuxt) で作ったので Vue のコードですが、適宜読み替えて下さい。LINE ログインのコアな部分は TypeScript に寄せてあります。

LineAccountService.ts

import type { OAuthCredential, UserCredential } from 'firebase/auth'
import {
  getAuth,
  OAuthProvider,
  signInWithPopup,
  unlink,
  linkWithPopup } from 'firebase/auth'

// 認証関連の関数を提供する
class LineAccountService {
  readonly providerIdLine: string = 'oidc.line'

  // LINE 連携
  signinWithLine(): Promise<OAuthCredential> {
    return new Promise((resolve, reject) => {
      const auth = getAuth()
      const provider = new OAuthProvider(this.providerIdLine)

      signInWithPopup(auth, provider)
        .then((result) => {
          // Get the OAuth access token and ID Token
          const credential = OAuthProvider.credentialFromResult(result)

          if (credential === null) {
            reject('credential が空でした。')
          }
          else {
            resolve(credential)
          }
        })
        .catch((error) => {
          // 失敗したら
          reject(error)
        })
    })
  }

  linkLine(): Promise<UserCredential> {
    return new Promise((resolve, reject) => {
      const auth = getAuth()

      const provider = new OAuthProvider(this.providerIdLine)

      if (!auth.currentUser) {
        reject()
      }
      else {
        linkWithPopup(auth.currentUser, provider).then((result) => {
          resolve(result)
        }).catch((error) => {
          reject(error)
        })
      }
    })
  }

  unlinkLine(): Promise<void> {
    return new Promise((resolve, reject) => {
      const auth = getAuth()

      // currentUser が空だったら
      if (auth.currentUser === null) {
        reject('currentUser が空でした。')
      }
      else {
        unlink(auth.currentUser, this.providerIdLine).then(() => {
          resolve()
        }).catch((error) => {
          reject(error)
        })
      }
    })
  }
}

export { LineAccountService }

LineLoginButton.vue

<template>
  <SecondaryButton
    block
    @click="lineLoginWeb()"
  >
    LINE でログインする
  </SecondaryButton>
</template>

<script setup lang="ts">
import { defineEmits } from 'vue'
import type { OAuthCredential } from 'firebase/auth'
import SecondaryButton from '../../template/secondary-button/SecondaryButton.vue'
import { LineAccountService } from '~/model/domain/auth/LineAccountService'

// emit を定義
const emit = defineEmits<{
  finished: [credential?: OAuthCredential]
}>()

function lineLoginWeb() {
  // LINE アカウントでログイン
  const lineAccountService = new LineAccountService()
  lineAccountService.signinWithLine()
    .then((credential) => {
      emit('finished', credential)
    })
    .catch((error) => {
      console.error(error)
      // 失敗したら undefined を返す
      emit('finished', undefined)
    })
}
</script>

さいごに

Firebase と LINE ログインの連携は情報が少なく、古い情報もあったりして苦労しました。この記事が誰かの役に立てるとうれしいです。