LoginSignup
13
15

More than 3 years have passed since last update.

【RefreshToken】Vue.jsでAccessTokenのリフレッシュを行う共通処理【リフレッシュトークン】

Last updated at Posted at 2020-02-27

はじめに

APIリクエストの際にアクセストークンの有効期限が切れていた場合に、トークンのリフレッシュを行い再度本来のAPIリクエストを行う処理のサンプルです。

前提

トークンの保持はcookieで行っています。トークンの発行はflask_jwt_extendedというライブラリを使用しています。サーバーサイドの仕様によってリクエストは適宜変更してください。
axiosのバージョンは0.18.X系です。0.19.X系は共通処理に記述したwithCredentialsがうまく動作しないバグがあるみたいです。

App.vueで下記のaxios.js読み込んで使用します。

コード

axios.js
import Axios from 'axios'
import Vue from 'vue'

const http = Axios.create({
    // 共通定義
    baseURL: 'http://localhost:5000/api/v1',
    withCredentials: true,
    headers: {
        "Content-Type": "application/json",
        "X-Requested-With": "XMLHttpRequest"
    }
})

http.interceptors.response.use((response) => {
    // APIのリクエストに成功した場合はそのまま結果を返す
    return response;
}, error => {
    // エラーかつトークン切れ(401)の場合
    if (error.config && error.response && error.response.status === 401) {
        // トークンリフレッシュのエンドポイントにリクエスト
        http
            .post(
                "/token/refresh",
                {},
                {
                    withCredentials: true,
                    headers: {
                        // flask_jwt_extendedの仕様
                        // CSRF対策。サーバサイドの実装によっては不要
                        "X-CSRF-TOKEN": Vue.$cookies.get("csrf_refresh_token")
                    }
                }
            )
            .then(res => {
                if (res.status == 200) {
                    // トークンの更新に成功
                    console.log("success token refresh");
                    const config = error.config;
                    // flask_jwt_extendedの仕様
                    // CSRF対策。新しく取得したアクセストークンに対応するCSRF対策文字列を設定。
                    // Authorizationヘッダーにトークンをセットする仕様の場合はここでトークンセット。
                    // 例:config.headers["Authorization"] = "bearer" + 取得したトークン
                    config.headers["X-CSRF-TOKEN"] = Vue.$cookies.get("csrf_access_token");
                    // 本来行いたかったAPIリクエストを再実行
                    return Axios.request(error.config);
                } else {
                    // トークンの更新に失敗した場合
                    console.log("failure token refresh");
                    // 現在の画面のパスをqueryにbackuriとしてセット。
                    // ログイン時にbackuriが存在していたらその画面に戻るように実装している場合のみセット。
                    // ただログイン画面に戻るだけならqueryは不要。
                    Vue.$router.push({
                        path: "login",
                        query: { backuri: Vue.$route.path }
                    });
                }
            })
            .catch(error => {
                console.log("failure token refresh");
                // エラーの場合もログイン画面に戻る
                Vue.$router.push({
                    path: "login",
                    query: { backuri: Vue.$route.path }
                });
            });
    }
    // エラー終了時にPromiseを返す
    return Promise.reject(error);
});
export default http

追記

7/14 改良版のソースがこちらにあります。
https://qiita.com/nqyutq/items/32fbcb56218594f4a341#%E3%83%88%E3%83%BC%E3%82%AF%E3%83%B3%E3%81%AE%E3%83%AA%E3%83%95%E3%83%AC%E3%83%83%E3%82%B7%E3%83%A5%E6%96%B9%E6%B3%95

13
15
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
13
15