Created
November 6, 2019 17:16
-
-
Save wooooodward/afe610206fa47560fdd0d94d2209247e to your computer and use it in GitHub Desktop.
Axios plugin example with request interceptor that adds JWT token to the auth header and 401 response interceptor to refresh token
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Vue from 'vue' | |
import axios from 'axios' | |
import store from '../store' | |
import { TokenService } from '../services/storage.service' | |
// Full config: https://github.com/axios/axios#request-config | |
let config = { | |
baseURL: | |
process.env.baseURL || | |
process.env.apiUrl || | |
'http://localhost:8000/api/v1/', | |
timeout: 1000, // 1 second | |
withCredentials: true, // check cross-site Access-Control | |
xsrfCookieName: 'csrftoken', | |
xsrfHeaderName: 'X-CSRFToken' | |
} | |
const _axios = axios.create(config) | |
_axios.interceptors.request.use( | |
config => { | |
// Add or remove auth header before request is sent | |
const token = TokenService.getToken() | |
if (token) { | |
config.headers.common['Authorization'] = 'JWT ' + token | |
} else { | |
delete config.headers.common['Authorization'] | |
} | |
return config | |
}, | |
error => { | |
return Promise.reject(error) | |
} | |
) | |
_axios.interceptors.response.use( | |
response => { | |
return response | |
}, | |
async error => { | |
// Intercept 401 response and retry | |
const token = TokenService.getToken() | |
if (error.response.status === 401 && token) { | |
if (error.response.config.url.includes('/token/refresh/')) { | |
store.dispatch('userModule/logout') | |
throw error | |
} else { | |
try { | |
await store.dispatch('userModule/reLogin') | |
return _axios.request({ | |
method: error.response.config.method, | |
url: error.response.config.url, | |
data: error.response.config.data | |
}) | |
} catch (e) { | |
store.dispatch('userModule/logout') // refresh failed | |
} | |
} | |
} | |
return Promise.reject(error) | |
} | |
) | |
Plugin.install = function(Vue) { | |
Vue.axios = _axios | |
window.axios = _axios | |
Object.defineProperties(Vue.prototype, { | |
axios: { | |
get() { | |
return _axios | |
} | |
}, | |
$axios: { | |
get() { | |
return _axios | |
} | |
} | |
}) | |
} | |
Vue.use(Plugin) | |
export default Plugin |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const ACCESS_TOKEN_KEY = 'access' | |
const REFRESH_TOKEN_KEY = 'refresh' | |
const TokenService = { | |
/** | |
* Manage the how Access Tokens are being stored and retrieved from storage. | |
* | |
* Current implementation stores to localStorage. Local Storage should always be | |
* accessed through this instance. | |
**/ | |
getToken() { | |
return localStorage.getItem(ACCESS_TOKEN_KEY) | |
}, | |
saveToken(accessToken) { | |
localStorage.setItem(ACCESS_TOKEN_KEY, accessToken) | |
}, | |
removeToken() { | |
localStorage.removeItem(ACCESS_TOKEN_KEY) | |
}, | |
getRefreshToken() { | |
return localStorage.getItem(REFRESH_TOKEN_KEY) | |
}, | |
saveRefreshToken(refreshToken) { | |
localStorage.setItem(REFRESH_TOKEN_KEY, refreshToken) | |
}, | |
removeRefreshToken() { | |
localStorage.removeItem(REFRESH_TOKEN_KEY) | |
} | |
} | |
export { TokenService } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment