⚡ New in AgentLink: Delegated AI Governance Find out more
Blog

Vue Authentication: The Basics and a Quick Tutorial

What Is Vue Authentication? 

Vue authentication refers to managing user access and identity in Vue.js applications. Authentication is a vital aspect of application security, ensuring that only authorized users can access certain parts and functionalities. In Vue.js, this process typically involves verifying user credentials against a backend service, utilizing tokens, and managing session states.

The approach helps maintain security across single-page applications (SPAs) built with Vue.js, where traditional server-side session handling is not feasible. By implementing authentication mechanisms, developers can secure user data and application resources.

How Vue Authentication Works

Vue authentication typically revolves around token-based methods, commonly using JSON Web Tokens (JWT). These tokens serve as a secure means of verifying a user’s identity across requests without relying on traditional server-side sessions. Here’s how the process generally works.

1. Initial Login and Token Retrieval

When a user submits their credentials (e.g., email and password), the frontend Vue app sends a request to the backend authentication server. If the credentials are valid, the server responds with an access token and, optionally, a refresh token.

The frontend stores these tokens—commonly in local storage or secure cookies—and uses them for subsequent authenticated requests.

2. Storing and Managing Tokens

While localStorage is frequently used due to its simplicity, it’s vulnerable to cross-site scripting (XSS). A more secure approach involves storing tokens in HttpOnly cookies, which are inaccessible to JavaScript. This reduces the attack surface for malicious scripts attempting to access authentication credentials.

In either case, the token acts as the user’s identity proof and must be attached to future API requests via the Authorization header.

3. Automatic Token Injection

To streamline authenticated communication, libraries like Axios can be configured with interceptors that automatically append the JWT to all outgoing HTTP requests. This ensures consistent and centralized handling of authentication headers across the application.

An example configuration:

axios.interceptors.request.use((config) => {
  const token = localStorage.getItem('token');
  if (token) {
    config.headers.Authorization = `Bearer ${token}`;
  }
  return config;
});

This pattern simplifies authenticated interactions without requiring manual token inclusion in every request.

4. Token Expiry and Refresh Flow

Tokens typically have expiration times to limit the risk of misuse. When a token expires, the frontend can use a refresh token—if implemented—to obtain a new access token without prompting the user to log in again. This exchange usually occurs silently in the background, often triggered by a failed API request due to token expiry.

The refresh mechanism ensures uninterrupted user sessions while maintaining security. Refresh tokens should always be stored securely (e.g., HttpOnly cookies) and rotated regularly to prevent abuse.

5. Handling Unauthorized Access

If a user attempts to access a protected resource with an invalid or missing token, the backend should respond with a 401 Unauthorized status. The frontend should intercept this response and take appropriate action, such as redirecting the user to the login page or initiating the refresh token flow.

Interceptors can help automate this response handling, improving user experience by seamlessly recovering from common authentication errors.

6. Session Termination

To log out a user, the frontend must clear the stored tokens and, if applicable, inform the backend to invalidate the refresh token. This ensures that stolen or leaked tokens can’t be reused to access protected resources. Logging out should also redirect users to a public route or a logout confirmation page.

Tutorial: Implementing Vue Authentication 

Here’s an overview of how to set up a Vue project and enable authentication.

Setting Up a Vue Project

Before implementing authentication in a Vue.js application, the first step is to create a new project. Ensure that you have both Node.js and npm installed. If they are not yet installed, download them from the Node.js website.

Once you have the necessary tools, follow these steps to create the project:

npm install -g @vue/cli
vue create secure-web-app
cd secure-web-app
npm run serve

The command npm install -g @vue/cli installs the Vue CLI globally, enabling you to create Vue projects using the vue create command. Next, vue create secure-web-app generates a new Vue.js project called secure-web-app. Running npm run serve starts the development server, and the project should be accessible at http://localhost:8080 in your browser, displaying the default Vue.js welcome page.

Creating the Login Component

The login component is essential for collecting user credentials, such as their email and password, and sending them to the backend for authentication. Below is a basic structure for a Vue.js login component:

<template>
  <div>
    <input type="email" v-model="email" placeholder="Email" />
    <input type="password" v-model="password" placeholder="Password" />
    <button @click="login">Login</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      email: '',
      password: ''
    };
  },
  methods: {
    login() {
      // Example: Send login request to the backend
      const payload = {
        email: this.email,
        password: this.password
      };

      // Perform the authentication request (e.g., using fetch or axios)
      // Example pseudo-code:
      // axios.post('/api/login', payload).then(response => {
      //   Store token in localStorage
      //   localStorage.setItem('token', response.data.token);
      // });

      console.log('Login payload:', payload);
    }
  }
};
</script>

In this component:

  • Two input fields are provided for the user to enter their email and password.
  • The v-model directive binds the input data to the email and password properties in the component’s data.
  • When the login button is clicked, the login method is triggered. This method sends the user’s credentials to the backend for authentication, and upon success, it stores the returned token (e.g., JWT) in the browser’s local storage. This token will be used to verify the user’s identity during their session.

Protecting Routes

To ensure that only authenticated users can access certain parts of your Vue.js application, use Vue Router and route guards. Vue Router allows developers to define meta fields, such as requiresAuth, that can indicate protected routes. The route guards then check if the user is authenticated before allowing them access to these routes.

To set up routes with Vue Router:

import Vue from 'vue';
import VueRouter from 'vue-router';
import Dashboard from './components/Dashboard.vue'; // Example component

Vue.use(VueRouter);

const routes = [
  {
    path: '/dashboard',
    component: Dashboard,
    meta: {
      requiresAuth: true // Mark this route as requiring authentication
    }
  },
  {
    path: '/login',
    component: () => import('./components/Login.vue') // Lazy-loaded login component
  }
];

const router = new VueRouter({
  routes
});

router.beforeEach((to, from, next) => {
  if (to.meta.requiresAuth) {
    const token = localStorage.getItem('token');
    if (token) {
      next(); // Proceed to route if user is authenticated 
    } else {
      next('/login'); // Redirect to login if not authenticated
    }
  } else {
    next(); // Proceed to route if it's not protected
  }
});

export default router;

This example uses the beforeEach navigation guard to check whether a route requires authentication by looking at the meta.requiresAuth field. If the route is protected and the token is not present in local storage, the user is redirected to the login page. Otherwise, the user is allowed to access the route.

Note: You will need to install vue-router via npm using the following command:

npm install vue-router

Implementing Role-Based Access Control

Role-based access control (RBAC) is a security approach that manages user access to different parts of an application based on their assigned roles. In Vue.js, implementing RBAC ensures that certain actions or pages are accessible only to users with the appropriate permissions.

Defining Roles and Permissions

To start, define roles (e.g., admin, user) and associate them with permissions. These roles will dictate what users can access in the application. Below is an example of how to define these roles and permissions in a Vue.js application:

const ROLES = {
  USER: 'user',
  ADMIN: 'admin'
};

const PERMISSIONS = {
  [ROLES.USER]: ['read'],            
  [ROLES.ADMIN]: ['read', 'write', 'delete'] 
};

module.exports = {
  ROLES,
  PERMISSIONS
};

In this setup:

  • USER role can only read.
  • ADMIN role has more privileges, including the ability to read, write, and delete.

Restricting Access Based on Roles

Once the roles and permissions are defined, you can configure Vue Router to restrict access to certain routes. This is done by adding meta fields in the route definitions that specify which roles are allowed to access those routes:

import Vue from 'vue';
import Router from 'vue-router';
import Home from './views/Home.vue';
import Login from './views/Login.vue';
import Dashboard from './views/Dashboard.vue';
import { ROLES } from './roles';

Vue.use(Router);

const routes = [
  { path: '/', component: Home },
  { path: '/login', component: Login },
  {
    path: '/dashboard',
    component: Dashboard,
    meta: {
      requiresAuth: true,
      allowedRoles: [ROLES.ADMIN] // Only admins can access
    }
  }
];

const router = new Router({
  mode: 'history',
  routes
});

In this example, the Dashboard route has a meta property allowedRoles set to [ROLES.ADMIN], meaning only users with the admin role can access it.

Implementing Route Guards for RBAC

Next, you need to implement a route guard that checks if the authenticated user has the required role before allowing access to protected routes. This can be achieved by using Vue Router’s beforeEach hook:

import jwt from 'jsonwebtoken'; // You may use jwt-decode or any other library to decode tokens

// Route guard to check authentication and role-based access
router.beforeEach((to, from, next) => {
  const token = localStorage.getItem('token'); // Retrieve token from local storage

  if (to.matched.some((route) => route.meta.requiresAuth)) {
    if (token) {
      const decodedToken = jwt.decode(token); // Decode the JWT to extract user role

      // Check if the user's role matches the allowed roles for the route
      const allowedRoles = to.meta.allowedRoles || [];
      if (allowedRoles.includes(decodedToken.role)) {
        next(); // Role is authorized, proceed to the route
      } else {
        next('/'); // User is not authorized, redirect to home
      }
    } else {
      next('/login'); // User is not authenticated, redirect to login
    }
  } else {
    next(); // Route does not require authentication
  }
});

export default router;

This code introduces two key checks:

  1. It verifies whether the route requires authentication by checking the requiresAuth meta field.
  2. It decodes the user’s token to extract the role and checks if it matches any of the roles allowed to access the route.

If the user’s role is not included in the allowedRoles for a particular route, they are redirected to the homepage or another designated route.

Best Practices for Vue Authentication 

Here are some of the ways that developers can ensure the most effective authentication in Vue.js applications.

Use HTTPS for All API Requests

Always ensure your application communicates over HTTPS. This encrypts the data exchanged between the client and the server, preventing attackers from intercepting sensitive information such as access tokens or user credentials.

To enforce HTTPS:

  • Configure your server to redirect HTTP traffic to HTTPS.
  • Obtain an SSL certificate from a trusted Certificate Authority (CA). Free options, like Let’s Encrypt, are widely available.
  • Use secure HTTP headers like Strict-Transport-Security (HSTS) to mandate HTTPS and protect against protocol downgrade attacks.

In local development, tools like mkcert or HTTPS modules in popular servers (e.g., webpack-dev-server) can simulate HTTPS environments, allowing you to test HTTPS-specific behaviors before deployment.

Securely Store Tokens

Tokens, such as JSON Web Tokens (JWTs), should never be stored in a way that makes them accessible to attackers, such as in localStorage or sessionStorage, where they are vulnerable to cross-site scripting (XSS) attacks.

Instead:

  • Use HttpOnly cookies to store tokens securely. These cookies cannot be accessed via JavaScript, providing protection against XSS attacks.
  • When cookies are used, set the Secure flag to ensure they are only sent over HTTPS. Additionally, use the SameSite attribute to limit cross-origin requests and reduce the risk of cross-site request forgery (CSRF) attacks.

If you must store tokens client-side for specific scenarios, implement strong XSS protection using Content Security Policies (CSPs) and ensure the application sanitizes all inputs rigorously.

Implement Proper Logout Functionality

Logout functionality ensures users can safely terminate their sessions and protect their accounts if they are on shared or public devices.

Key considerations:

  • Clear tokens and sensitive data from the client (e.g., remove tokens from local storage, clear cookies).
  • Invalidate the token server-side by maintaining a blacklist or adjusting the token’s expiration. This ensures the token cannot be reused after logout.
  • Provide users with a logout confirmation and feedback mechanism to verify successful session termination.

For additional security, consider implementing automatic logout for inactivity. This can be achieved by monitoring user activity and triggering the logout mechanism after a predefined idle period.

Regularly Update Dependencies

Keeping dependencies up to date ensures your application benefits from the latest security patches and improvements.

Best practices include:

  • Regularly audit your project with tools like npm audit or Snyk to identify vulnerabilities in third-party libraries.
  • Lock down dependency versions using package-lock.json or yarn.lock to prevent unexpected updates from introducing breaking changes.
  • Before updating major dependencies, test changes in a staging environment to ensure compatibility and stability.

For critical packages, like those related to authentication (e.g., Axios, JWT libraries), prioritize updates as soon as vulnerabilities are disclosed. Monitor repositories for security advisories, or subscribe to security mailing lists.

Educate Users on Security Practices

User behavior is often the weakest link in application security. Educate your users to foster safe habits that reduce the likelihood of breaches.

Effective strategies include:

  • Encourage the use of strong, unique passwords and provide hints for password creation (e.g., at least 12 characters with a mix of letters, numbers, and symbols). Integrate password strength meters in registration forms.
  • Promote the use of password managers for better password hygiene. Consider adding support for passkey or biometrics if feasible.

Additionally, inform users to log out of shared or public devices and avoid accessing sensitive accounts over unsecured Wi-Fi. Through these measures, you can enhance the overall security posture of your Vue.js application.

Related content: Read our guide to JWT authentication

Managed Authentication for Vue Apps with Frontegg

Authentication in Vue is easy to start and painful to maintain. As your app grows, so do the requests for SSO, MFA, role changes, and access updates, all of which tend to land back on engineering. That work is critical, but it rarely moves the product forward.

Frontegg gives Vue teams a managed authentication layer that handles the heavy lifting long after the initial setup. Developers stay in control of integration and architecture, while Customer Success, Product, and Infosec teams can manage identity tasks on their own. The outcome is fewer interruptions, less ongoing auth maintenance, and more time for engineers to focus on building what actually differentiates the product.