🔥

axiosでtoken期限が切れていたときにtoken更新して再リクエスト処理するやつ

2022/02/06に公開

概要

axiosでtoken期限が切れていたときにtoken更新して再リクエスト処理するやつです。
今個人で作ろうとしているwebアプリで認証周りが慣れていなくごちゃごちゃしたので書いておきます。認証はfirebaseAuthを使っています。

axiosではaxios.interceptorsでapi叩く時の前処理とか後処理を書いておくことができます。
これでレスポンスが401ステータスで返ってきたときにfirebaseから新しいtokenを取得して同じリクエストを再度送ります。
Interceptors

axiosインスタンスをつくっておく

ヘッダーにアクセストークンをつけるのでインスタンスつくって設定しておきます。
baseURLとtimeoutは別のファイルにまとめて書いておきました。

const instance = axios.create({
  baseURL: defaultApiConfig.baseURL,
  headers: { Authorization: `Bearer ${window.localStorage.getItem('access_token')}` },
  timeout: defaultApiConfig.timeout
});

interceptors

再リクエストの処理を書いていきます。
401で返ってきたときはfirebaseで新しいtokenを取って、それでエラーが返ってきたらとりあえずトップに戻す処理を入れました。
axios.requestにエラーで返ってきたerr.configを入れるとそのまま失敗したリクエストの設定を使ってリクエストできます。
全く同じリクエストだとまたエラーになるのでtokenだけ新しいものにしておきます。

instance.interceptors.response.use(
    (res) => {
      return res;
    },
    async (err) => {
      if (err.response.status === 401 && firebaseAuth.currentUser) {
        const newToken = (await firebaseAuth.currentUser.getIdTokenResult()).token;
        window.localStorage.setItem('access_token', newToken);
        const res = await axios
          .request({
            ...err.config,
            headers: {
              Authorization: `Bearer ${window.localStorage.getItem('access_token')}`
            }
          })
          .catch((err) => {
            window.location.href = '/';
          });
        return res;
      }
    }
  );

最終形態

最終的なコードは以下な感じです。

const mainAxios = () => {
  const instance = axios.create({
    baseURL: defaultApiConfig.baseURL,
    headers: { Authorization: `Bearer ${window.localStorage.getItem('access_token')}` },
    timeout: defaultApiConfig.timeout
  });

  instance.interceptors.response.use(
    (res) => {
      return res;
    },
    async (err) => {
      if (err.response.status === 401 && firebaseAuth.currentUser) {
        const newToken = (await firebaseAuth.currentUser.getIdTokenResult()).token;
        window.localStorage.setItem('access_token', newToken);
        const res = await axios
          .request({
            ...err.config,
            headers: {
              Authorization: `Bearer ${window.localStorage.getItem('access_token')}`
            }
          })
          .catch((err) => {
            window.location.href = '/';
          });
        return res;
      }
    }
  );

  return instance;
};

使うときは

await mainAxios().get(endpoint)

こんな感じです。

参考

axiosで認証切れエラー起こしたリクエストを再現してリカバリーする
Vue.jsにFirebase Authenticationで認証機能を実装する

Discussion