1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

FirebaseAuthとGoogle OAuthではまった話

Posted at

🏁 忙しい人のための結論

  • 問題:FirebaseでGoogleログインした後、1時間後にGoogle Calendar APIが401エラーで失敗する
     → Firebaseの認証は有効なのに、Google側の認証が切れてしまう

  • 原因:FirebaseのIDトークンとGoogleのOAuthトークンは別物
     → FirebaseのIDトークンは自アプリ向け、Google APIはOAuth2トークンで別認証が必要

  • 解決
     1. Googleログイン時に Blocking Function を使い、GoogleのOAuthトークンを取得してFirestoreに保存
     2. フロントはFirebase IDトークンでFunctionsを呼び出し
     3. FunctionsがFirestoreからGoogleトークンを取得し、OAuth2ClientでAPIを実行

🔹1. はじめに

個人開発で、FirebaseからGoogle Calendar APIを呼び出して
Googleカレンダーの内容を分析するWebアプリを作っていました。

Firebase Authenticationを使ってGoogleログインを実装し、
そこから取得した予定データを分析・可視化する構成です。

🧩 使用技術・構成概要

コンポーネント 役割
Firebase Authentication Googleログイン+Firebase IDトークン発行
Next.js(フロント) Firebaseトークンを保持し、直接Google Calendar APIを呼び出し
Google Calendar API カレンダー情報を返却(ただし1時間後に401エラー)

🔹 2. 想定フローと実装方針

初期実装では以下のようなフローを想定していました。

  1. Googleでログイン
  2. Firebaseの認証トークンを取得し、フロントで保持
  3. そのFirebaseトークンを使ってGoogle Calendar APIを実行
  4. Googleカレンダーの情報を取得して表示

実際に実装したコード上は問題なく動作し、最初はカレンダー情報が取得できていました。

🔹 3. はまった現象

ところが、1時間後に再度APIを叩くと認証エラーが発生。
Firebase上ではログイン状態が維持されているにもかかわらず、
Google Calendar APIの呼び出しだけが401エラーで失敗していました。

「Firebaseではログインしているのに、なぜGoogleカレンダーは認証されないのか?」

この状態に1か月ほどハマっていました。

🔹 4. 原因の正体

原因は、Firebaseの認証トークンとGoogle Calendar APIの認証トークンは別物だったことです。

Firebaseの認証トークン(Firebase ID Token)はFirebaseサービスへの認可専用。
Google Calendar APIはOAuth2のAccess Tokenによって別途認証される仕組みです。

つまり以下のような違いがあります。

種類 用途 有効期限
Firebase ID Token Firebaseサービス用 約1時間
Google OAuth Access Token Google API用 約1時間(Refresh可能)

🔹 5. 解決方法

最終的には以下のようなフローに変更することで解決しました。

  1. Googleログインを実行(Firebase Authentication)
  2. ブロッキング関数でGoogleのOAuthトークンを取得し、Firestoreに保存
  3. フロントはFirebase IDトークンを使ってCloud Functionsを呼び出す
  4. FunctionsがFirestoreからGoogleトークンを取得し、Calendar APIを呼び出す
  5. 必要に応じてRefresh TokenでAccess Tokenを再発行
コンポーネント 役割
Firebase Authentication Googleログインによる認証(IDトークン発行)
Firebase Blocking Function Google OAuthトークンを取得し、Firestoreへ安全に保存
Firestore Googleトークンやユーザー設定を保持
Cloud Functions FirestoreからGoogleトークンを取得し、OAuth2ClientでCalendar APIを実行
Google Calendar API ユーザーの予定データを取得
Next.js(フロント) FirebaseトークンでFunctionsを呼び出し、取得データを表示

🧠 なぜブロッキング関数を使うのか

Firebaseの通常のGoogleログインでは、GoogleのOAuth認証情報(Access Token / Refresh Token)を取得できません
Google APIを利用するには、Blocking Functionをかませてトークンをサーバー側で取得する必要があります
Blocking Functionは、ログインリクエストの途中(beforeSignIn)で GoogleのOAuth認証情報にアクセスできるタイミングを提供します。

🔹 6. ブロッキング関数の作成

Firebase Authentication の Blocking Functions(ブロッキング関数) には、主に次の2種類があります。

  • beforeCreate

    • ユーザーが 新規登録 する直前に実行される
    • 初期データ登録や、初回のみ必要な処理(例:Firestoreへのユーザープロファイル作成)に利用
  • beforeSignIn

    • 既存ユーザーが ログイン する直前に実行される
    • 毎回ログイン時に行いたい処理(例:Googleトークンの更新・再取得)に利用

今回のケースでは、Google Calendar APIを利用するためのOAuthトークンをログイン時に取得・更新する必要があるため、beforeSignIn のみを実装しています。

import {beforeUserSignedIn} from 'firebase-functions/v2/identity';
import { AuthService } from '../services/auth/service';

export const beforesignedin = beforeUserSignedIn((event) => {
  // firestoreにGoogle OAuthトークンを保存
  AuthService.saveGoogleTokens(
    event.data.uid, 
    event.credential.accessToken,
    event.credential.refreshToken
  );
});

上記関数をデプロイしてください。

🔹 7. ブロッキング関数の設定

以下画面のログイン前に先ほど作成した関数を設定してください。
ブロッキング関数で取得したい情報にチェックするのを忘れずに。

image.png

🔹 8. まとめ

今回1か月もこの事象にはまったのは、まったくの初見のfirebase、google apiをろくに調べずに実装をほぼAIに任せていたからです。
誰かが言っていた「バイブコーディングは9割を形にするのは速いが、残り1割に時間がかかる」というのを、身をもってい体験しました。
とほほ。。。

1
1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?