Vue-Element-Admin request.js Axios Wrapper: Token Refresh Mechanism and 401 Error Handling
The request.js wrapper in vue-element-admin does not implement automatic silent token refresh; instead, it detects expired tokens via custom backend response codes (50008, 50012, 50014) and forces a user re-login, while treating standard HTTP 401 errors as generic network failures.
The request.js file is the central HTTP client configuration in the PanJiaChen/vue-element-admin repository, providing a pre-configured Axios instance with interceptors for authentication and error handling. Understanding its token lifecycle is essential for developers customizing authentication flows or debugging session expiration issues.
How request.js Injects Authentication Tokens
Request Interceptor: Automatic Header Injection
Before any HTTP request leaves the application, the request interceptor in src/utils/request.js (lines 13-24) checks the Vuex store for an existing session. If store.getters.token returns a value, the interceptor retrieves the actual token string via getToken() from src/utils/auth.js and injects it into the request headers as X-Token.
// src/utils/request.js - Request interceptor
service.interceptors.request.use(
config => {
if (store.getters.token) {
config.headers['X-Token'] = getToken()
}
return config
},
error => {
console.log(error)
return Promise.reject(error)
}
)
This ensures that authenticated routes receive the necessary credentials without manual header configuration in every API call.
Business Logic Error Handling in Response Interceptors
Custom Response Codes vs HTTP Status Codes
The wrapper differentiates between transport-layer failures (HTTP 4xx/5xx) and application-layer errors (custom JSON codes). In src/utils/request.js (lines 45-68), the response interceptor examines the code field in the response body. While a successful response carries code: 20000, specific values trigger authentication-related actions:
- 50008: Illegal token (tampered or malformed)
- 50012: Other clients logged in (session concurrency)
- 50014: Token expired
When these codes appear, the interceptor opens an Element-UI MessageBox dialog prompting the user to re-login:
// Simplified excerpt from lines 45-68
if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
MessageBox.confirm(
'You have been logged out, you can cancel to stay on this page, or log in again',
'Confirm logout',
{
confirmButtonText: 'Re-Login',
cancelButtonText: 'Cancel',
type: 'warning'
}
).then(() => {
store.dispatch('user/resetToken').then(() => {
location.reload() // Force reload to reset router and state
})
})
}
The Absence of Silent Token Refresh
No automatic token refresh mechanism exists in the current implementation. Unlike modern OAuth2 clients that might call a /refresh endpoint upon detecting an expired access token, this wrapper immediately invalidates the session and requires manual user intervention.
The resetToken action in src/store/modules/user.js clears the Vuex state and removes the token from cookies/local storage, but it does not attempt to exchange a refresh token or negotiate a new session silently. This design assumes the backend uses short-lived tokens or session-based authentication where re-authentication is the preferred security posture.
Handling HTTP 401 Unauthorized Errors
When the server returns a genuine HTTP 401 status (or any other non-2xx status) without the custom JSON body expected by the business logic interceptor, the error falls into the second response interceptor handler at lines 74-81:
// src/utils/request.js - Error interceptor
service.interceptors.response.use(
response => { /* ... success handling ... */ },
error => {
console.log('err' + error) // Debug logging
Message({
message: error.message,
type: 'error',
duration: 5 * 1000
})
return Promise.reject(error)
}
)
Standard 401 errors are treated as generic network failures. The interceptor displays the error message via Element-UI's Message component and propagates the rejected promise to the calling code. No automatic logout, token refresh, or redirection occurs for HTTP-level authentication failures.
Practical Implementation Examples
Making an Authenticated Request
API functions import the configured instance and benefit from automatic token injection:
import request from '@/utils/request'
export function fetchUserProfile() {
// X-Token header is injected automatically if user is logged in
return request({
url: '/user/profile',
method: 'get'
})
}
Catching 401 Errors in Components
Since the wrapper rejects the promise for HTTP errors, components can handle authentication failures explicitly:
export default {
async created() {
try {
await this.$store.dispatch('user/getInfo')
} catch (err) {
// err.message contains the HTTP status text
console.warn('Authentication failed:', err)
this.$router.push('/login')
}
}
}
Simulating Token Expiration Handling
When the backend returns code: 50014, the user sees a confirmation dialog. Upon confirmation, the application state resets:
// This flow occurs automatically inside request.js when code === 50014
store.dispatch('user/resetToken').then(() => {
// Clears localStorage/cookies and Vuex state
location.reload() // Full page reload clears in-memory router state
})
Summary
- Automatic injection: The request interceptor adds
X-Tokenheaders by reading fromstore.getters.tokenviagetToken()insrc/utils/auth.js. - Custom code handling: Responses with codes 50008, 50012, or 50014 trigger a logout dialog and dispatch
user/resetToken, forcing re-authentication. - No silent refresh: The wrapper does not implement refresh token logic; expired sessions always require user action.
- HTTP 401 treatment: Standard 401 responses surface as generic errors in the Axios error interceptor without automatic logout or token clearing.
- State management: Token removal occurs through
src/store/modules/user.js, ensuring both Vuex and persistent storage are cleared before reloading.
Frequently Asked Questions
How does request.js detect an expired token?
The wrapper checks the code field in JSON responses for specific values: 50014 (token expired), 50008 (illegal token), or 50012 (other clients logged in). When these appear, it displays a confirmation dialog and dispatches the user/resetToken action to clear the session. It does not inspect JWT expiration dates or attempt proactive validation.
What is the difference between HTTP 401 and the custom 50014 code?
HTTP 401 is handled in the Axios error interceptor (lines 74-81) as a network-level failure, displaying a generic error message and rejecting the promise. The custom 50014 code is handled in the success interceptor (lines 45-68) as a business logic condition, triggering the logout/re-login flow. The application expects the backend to return 200 OK with a JSON body containing these custom codes rather than standard HTTP 401 statuses.
Where is the authentication token stored in vue-element-admin?
The token is retrieved via getToken() from src/utils/auth.js, which abstracts the storage mechanism (typically cookies or localStorage). The request interceptor accesses it through store.getters.token to check for existence, then reads the actual value via getToken() to inject into the X-Token header.
Can I add automatic token refresh to request.js?
Yes, but it requires modifying src/utils/request.js to intercept 401 errors or specific custom codes, call a refresh endpoint, update the token via setToken(), and retry the original request. The current implementation deliberately avoids this pattern for simplicity, instead forcing a full page reload to clear all state when sessions expire.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →