📑

Firebase Accessトークン期限切れ更新 x Axios

2 min read 1

概要

以前書いた、「Nuxt.js(SSR) + Firebase Authenticationまとめ」で取得したAccess_Tokenなどが切れている場合にどのようにリフレッシュをするかなどを記事にしました。

https://zenn.dev/watson_sei/articles/f4db7312494525

環境に関して!

Backend(Middlware含む)は、割愛させていただきます。

下記の図が今回の仕組みです。急いで作ったのでわかりづらいですがまあぱっと見で理解してください

トークン切れ判定と、トークンを更新

access_tokenが切れている場合の判定

onErrorエラーが発生した時に発生するイベントを利用して、エラーの時の処理を始めます。
status code 401が返ってきて、さらに詳しい条件分岐で"Token has expired"が返ってきたらトークンが切れているとわかるのでトークン更新処理を実行します。

access_tokenをrefresh_tokenで更新する

Nuxt/Firebaseでは、リフレッシュトークンを利用した説明が具体的になかったので以下の方法で実装しました。詳しいHeader・Body情報は公式ドキュメントからチェックしてみてください!

https://firebase.google.com/docs/reference/rest/auth/#section-refresh-token

再度リクエスト

再度同じリクエストをaxiosで書くのはめんどくさいので、axios(error.config)で簡単に再リクエストを実装しちゃいます。

plugins/axios.js
import axios from "axios";

export default function ({ $axios, redirect }) {
  $axios.onError(error => {
    if (error.response.status === 401) {
      if (error.response.data.message === "Token has expired") {
        const params = new URLSearchParams();
        params.append("grant_type", "refresh_token")
        params.append("refresh_token", localStorage.getItem('refresh_token'))
        axios.post(`https://securetoken.googleapis.com/v1/token?key=${process.env.apiKey}`, params, {
          headers: {
            'Content-Type': 'application/x-www-form-urlencoded',
          }
        }).then((response) => {
          localStorage.removeItem('access_token')
          localStorage.setItem('access_token', response.data.access_token)
          localStorage.removeItem('refresh_token')
          localStorage.setItem('refresh_token', response.data.refresh_token)
          axios(error.config)
        }).catch(() => {
          redirect('/room')
        })
      }
    }
  })
}

参考

Nuxt.jsでaxiosのリクエストをフックする
Firebase Auth の refreshトークンの取得とIDトークンの更新

Discussion

初めまして。
当記事、大変参考になり助かりました。

参考にしつつ、コードを書いていたのですが、トークンのリフレッシュ処理がどうにもうまく動かない状況にあります。
もし、すぐお分かりになるようでしたらご教授いただければ大変助かります。

※firebaseの「https://securetoken〜」へのリクエストが上手くいかないため、当処理を抜き出して実行しているのですが、同一エラーとなります。

【firebaseへの更新リクエスト抜粋した処理】
refresh() {
const params = new URLSearchParams()
params.append('grant_type', 'refresh_token')
params.append('refresh_token', localStorage.getItem('refresh_token'))
this.$axios
.post(
https://securetoken.googleapis.com/v1/token?key=${process.env.FIREBASE_API_KEY},
params,
{}
)
.then((response) => {
console.log('リフレッシュ成功' + response)
localStorage.removeItem('access_token')
localStorage.setItem('access_token', response.data.access_token)
localStorage.removeItem('refresh_token')
localStorage.setItem('refresh_token', response.data.refresh_token)
})
.catch(() => {
console.log('リフレッシュエラー' + params)
})
},

【firebaseからのレスポンス内容】
error: {code: 401,…}
code: 401
message: "Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project."
status: "UNAUTHENTICATED"

Google Chromeでリクエスト内容を確認したのですが、key、grant_type、refresh_tokenは正常に設定されてリクエストが送られているように見えます。

宜しくお願いいたします。

ログインするとコメントできます