🔥

【有効期限に注意】SPAでfirebaseのidTokenを使ってAPIリクエストする

2022/03/17に公開

firebase-authのidTokenをAPIリクエスト時にheaderのAuthorizationに渡して認証するという実装をした時の備忘録です。

ざっくり構成

APP:   計測や商品管理のできるダッシュボード
FRONT: React 
API:   REST
AUTH:  firebase idToken

困った点

idTokenの有効期間は1時間なので、初期描画の際に取得しておくだけでは認証エラーが割と頻発する(今回の実装ではバックエンドから401が返るようになってます)

対応の選択肢

下記のどちらかかなと

  1. フロントエンドでリクエスト前に毎回idTokenを取得し直して認証する
  2. リクエストして401が返却されたらidTokenを取得してリトライ

各対応のデメリット

「リクエスト前に毎回idTokenを取得」

  • 無駄なtoken取得メゾットを呼ぶことになる

「401が返却されたらidTokenを取得してリトライ」

  • tokenをグローバルステートで管理する必要がある
  • リトライ+state更新するのと、リクエストの引数に毎回stateで持っているidTokenを渡し、headerに設定する必要がある

と思っていて、複雑化させたくない気持ちが強かったので、「リクエスト前に毎回idTokenを取得」 する方針で実装することにしました。

ファイルの中身

細かい詳細は省きざっくりですが

firebaseのwrap用ファイル

import firebase from 'firebase/compat'
import firebaseApp from 'firebase/compat/app'
import * as firebaseAuth from 'firebase/auth'

const firebaseConfig = {
  //configの内容
}

firebaseApp.initializeApp(firebaseConfig)
firebase.auth().setPersistence(firebaseApp.auth.Auth.Persistence.LOCAL)

export const auth = firebaseAuth

export type FireBaseUser = firebaseAuth.User | null

初期化と認証用のモジュールとtypeをwrapしてます

axiosをクライアント化してwrapしているファイル

import _axios from 'axios'
import { auth } from '../firebase'

const client = _axios.create({
  baseURL: `${process.env.REACT_APP_PUBLIC_SITE_URL}`,
  headers: {
    'Content-Type': 'application/json',
    'X-Requested-With': 'XMLHttpRequest',
  },
  responseType: 'json',
})

client.interceptors.request.use(async (request) => {
  //リクエスト前に毎回idTokenを取得する
  const idToken = await auth.getAuth().currentUser?.getIdToken()
  request.headers.Authorization = idToken
  return request
})

リクエスト前に何か処理を行いたい場合は、interceptors.requestを使います
この中でidTokenを取得してheaders.Authorizationに設定します。

これでidTokenはいつでもフレッシュになるので、有効期限に関して注意する必要がなくなりました

有効期限を逐一チェックしてidTokenを取得するか切り分けるっていう手もあると思いますが、今回は選択肢に入りませんでした。

迷ったらsimple is bestの精神でやってます。

ありがとうございました。

Discussion