How vue-element-admin Manages JWT Tokens in Cookies Using auth.js

The auth.js utility in PanJiaChen/vue-element-admin stores JWT tokens in browser cookies using the js-cookie library with minimal default security settings, leaving XSS mitigation and CSRF protection to the implementing developer.

The PanJiaChen/vue-element-admin project provides a lightweight authentication helper in src/utils/auth.js that handles JWT tokens in cookies. This utility offers a simple API for token persistence across browser sessions but implements basic defaults that require additional security hardening for production applications.

How auth.js Stores JWT Tokens in Cookies

Core Token Management Functions

The src/utils/auth.js module exports three functions that wrap the js-cookie library to provide CRUD operations for authentication tokens:

import Cookies from 'js-cookie'

const TokenKey = 'Admin-Token'

export function getToken() {
  return Cookies.get(TokenKey)
}

export function setToken(token) {
  return Cookies.set(TokenKey, token)
}

export function removeToken() {
  return Cookies.remove(TokenKey)
}

These functions treat the JWT as an opaque string. When a user authenticates via src/api/user.js, the server returns a JWT that the client passes to setToken(). Subsequent API calls in src/utils/request.js retrieve the token using getToken() to attach Bearer authentication headers, while removeToken() clears the cookie during logout operations.

By default, js-cookie creates a JavaScript-accessible cookie without the HttpOnly flag. The utility does not configure additional attributes such as Secure, SameSite, or expiration times, relying entirely on library defaults. This configuration means the token remains exposed to JavaScript execution contexts and transmits over both HTTP and HTTPS connections.

Security Considerations and Vulnerabilities

XSS Exposure Risks

Because the cookie is readable by JavaScript, a successful cross-site scripting (XSS) attack could extract the JWT via document.cookie and exfiltrate it to attacker-controlled servers. Unlike HttpOnly cookies, which JavaScript cannot access, this implementation leaves the authentication token vulnerable to script injection attacks targeting the DOM.

Transport Security Concerns

Without the Secure flag, the cookie may transmit over unencrypted HTTP connections, exposing the JWT to network eavesdropping and man-in-the-middle attacks. The default configuration in auth.js does not enforce HTTPS-only transmission, potentially allowing token interception on insecure networks.

CSRF Protection Gaps

Storing JWTs in cookies causes browsers to automatically include the token in same-origin requests. This behavior creates potential cross-site request forgery (CSRF) vectors if the backend does not validate Origin/Referer headers or implement anti-CSRF tokens. While localStorage would not automatically send tokens, cookie-based storage requires additional server-side CSRF protections.

Implementing Security Enhancements

Developers must manually configure security attributes when calling setToken(). While HttpOnly cannot be set via JavaScript (requiring server-side Set-Cookie headers), other critical protections can be implemented client-side:

// Secure cookie configuration for production
Cookies.set(TokenKey, token, {
  expires: 7,               // 7-day expiration
  secure: true,             // HTTPS only
  sameSite: 'strict'        // Strict CSRF protection
})

For production environments requiring HttpOnly cookies, the backend must set the cookie directly via HTTP response headers rather than using the client-side auth.js utility. This approach prevents JavaScript access entirely, mitigating XSS risks at the cost of requiring server-side session management.

Practical Usage Examples

Storing Tokens After Authentication

import { setToken } from '@/utils/auth'
import { login } from '@/api/user'

async function handleLogin(credentials) {
  const { data } = await login(credentials)
  setToken(data.token)
}

Attaching Tokens to API Requests

import { getToken } from '@/utils/auth'
import request from '@/utils/request'

export function fetchUserInfo() {
  const token = getToken()
  return request({
    url: '/user/info',
    method: 'get',
    headers: { Authorization: `Bearer ${token}` }
  })
}

Clearing Tokens on Logout

import { removeToken } from '@/utils/auth'

function logout() {
  removeToken()
  // Additional cleanup logic
}

Summary

  • The src/utils/auth.js utility provides minimalist JWT storage using js-cookie with three core functions: getToken(), setToken(), and removeToken().
  • Default configurations lack HttpOnly, Secure, and SameSite attributes, creating XSS and CSRF vulnerabilities that require developer intervention.
  • Production implementations must manually configure secure cookie attributes, though HttpOnly requires server-side cookie setting via HTTP headers.
  • The token is stored under the key Admin-Token and retrieved for Bearer token authentication in API requests through src/utils/request.js.

Frequently Asked Questions

How does auth.js store JWT tokens in vue-element-admin?

The utility uses the js-cookie library to store JWTs as browser cookies under the key Admin-Token. It provides getter, setter, and remover functions that wrap the library's API, treating tokens as opaque strings without additional client-side encryption or encoding.

No. The default implementation creates JavaScript-accessible cookies without the HttpOnly flag. Setting HttpOnly requires server-side configuration via Set-Cookie headers, as client-side JavaScript cannot create HttpOnly cookies by design.

What security risks exist with the default auth.js implementation?

The default configuration exposes tokens to XSS attacks through JavaScript access, transmits over potentially unencrypted HTTP connections without the Secure flag, and automatically includes tokens in cross-site requests, creating CSRF vulnerabilities without additional backend validation.

How can I secure JWT storage in vue-element-admin?

Pass security options to Cookies.set() including secure: true for HTTPS-only transmission, sameSite: 'strict' for CSRF mitigation, and explicit expiration dates. For maximum security, implement HttpOnly cookies by having the backend set cookies directly via HTTP headers rather than using the client-side utility.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →