coderain blog

Axios Basic Auth Not Working in Vue: How to Fix 401 Authorization Error for CORS API Calls

If you’re building a Vue.js application and using Axios to make API calls with Basic Authentication, encountering a 401 Unauthorized error—especially when combined with CORS (Cross-Origin Resource Sharing) issues—can be frustrating. You’ve double-checked your username and password, verified the Axios setup, and yet the error persists.

This guide will demystify why Axios Basic Auth fails in Vue apps, break down the relationship between 401 errors and CORS, and provide a step-by-step solution to fix the problem. By the end, you’ll understand how to configure Axios correctly and ensure your server handles CORS preflight requests, putting an end to those stubborn authorization errors.

2026-01

Table of Contents#

  1. Understanding the Problem: 401, Basic Auth, and CORS
  2. Common Causes of Axios Basic Auth Failures in Vue
  3. Step-by-Step Fixes
  4. Testing the Solution
  5. Troubleshooting Tips
  6. Conclusion
  7. References

Understanding the Problem: 401, Basic Auth, and CORS#

Before diving into fixes, let’s clarify the key concepts at play:

What is a 401 Unauthorized Error?#

A 401 Unauthorized response indicates the server rejected your request because it lacks valid authentication credentials. For Basic Auth, this means the server didn’t recognize or accept the username/password you sent.

How Basic Authentication Works#

Basic Auth is a simple authentication method where:

  1. The client sends a username and password encoded as a Base64 string in the Authorization HTTP header.
  2. The header format is: Authorization: Basic <base64-encoded-username:password>.
  3. Example: If your username is alice and password is secure123, the header becomes Authorization: Basic YWxpY2U6c2VjdXJlMTIz.

What is CORS, and Why Does It Matter?#

CORS is a browser security feature that blocks cross-origin requests (e.g., your Vue app at http://localhost:8080 calling an API at https://api.example.com). To allow such requests, the server must return specific CORS headers (e.g., Access-Control-Allow-Origin).

Critical Note: When your Axios request includes non-simple headers (like Authorization), the browser first sends a preflight request (using the OPTIONS method) to the server to check if the actual request is allowed. If the server doesn’t respond to this preflight with valid CORS headers, the browser blocks the real request—often leading to a misleading 401 error (even if your credentials are correct!).

Common Causes of Axios Basic Auth Failures in Vue#

Most 401 errors with Axios Basic Auth in Vue stem from one (or more) of these issues:

  1. Incorrect Axios Configuration: Missing or malformed Authorization header.
  2. CORS Misconfiguration on the Server: The server isn’t returning headers like Access-Control-Allow-Headers: Authorization or Access-Control-Allow-Origin.
  3. Unsupported Preflight Requests: The server doesn’t handle OPTIONS preflight requests, so the browser blocks the actual request.
  4. Base64 Encoding Errors: Invalid encoding of username/password (e.g., special characters not handled correctly).

Step-by-Step Fixes#

Let’s resolve these issues with actionable steps.

1. Verify Axios Basic Auth Setup#

First, ensure Axios is configured to send the Authorization header correctly. There are two common ways to set Basic Auth in Axios:

Option 1: Manual Authorization Header#

Explicitly set the Authorization header in your Axios request:

// In your Vue component or service
import axios from 'axios';
 
const fetchData = async () => {
  const username = 'alice';
  const password = 'secure123';
  const authHeader = 'Basic ' + btoa(`${username}:${password}`); // Encode to Base64
 
  try {
    const response = await axios.get('https://api.example.com/data', {
      headers: {
        'Authorization': authHeader, // Critical: Include the header
        'Content-Type': 'application/json' // Optional, but common for APIs
      }
    });
    console.log('Success:', response.data);
  } catch (error) {
    console.error('Error:', error.response?.status); // Log 401, 403, etc.
  }
};

Option 2: Use Axios’ auth Config (Simpler)#

Axios provides a built-in auth option to auto-generate the Authorization header. This avoids manual Base64 encoding:

const fetchData = async () => {
  try {
    const response = await axios.get('https://api.example.com/data', {
      auth: {
        username: 'alice',
        password: 'secure123' // Axios auto-encodes this to Basic Auth header
      }
    });
    console.log('Success:', response.data);
  } catch (error) {
    console.error('Error:', error);
  }
};

Why This Works: Axios automatically converts the auth object into the Authorization: Basic ... header, reducing human error.

2. Fix Server-Side CORS Configuration#

Even if your Axios setup is correct, the server must allow cross-origin requests with the Authorization header. Below are examples for popular server frameworks:

Example 1: Node.js/Express#

Use the cors middleware and configure it to allow the Authorization header:

// Install: npm install cors
const express = require('express');
const cors = require('cors');
const app = express();
 
// Configure CORS to allow your Vue app's origin
const corsOptions = {
  origin: 'http://localhost:8080', // Replace with your Vue app's URL
  allowedHeaders: ['Authorization', 'Content-Type'], // Allow Authorization header
  methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'], // Allow needed methods
  credentials: true // Only if using cookies (rare for Basic Auth)
};
 
app.use(cors(corsOptions));
 
// Your API routes (e.g., /data)
app.get('/data', (req, res) => {
  // Verify Basic Auth here (e.g., using express-basic-auth)
  res.json({ message: 'Authenticated data' });
});
 
app.listen(3000, () => console.log('Server running on port 3000'));

Example 2: Django#

Use django-cors-headers to configure CORS:

# Install: pip install django-cors-headers
# settings.py
INSTALLED_APPS = [
  # ...
  'corsheaders',
  # ...
]
 
MIDDLEWARE = [
  'corsheaders.middleware.CorsMiddleware', # Place at the top
  # ... other middleware
]
 
# Allow your Vue app's origin
CORS_ALLOWED_ORIGINS = [
  "http://localhost:8080",
]
 
# Allow the Authorization header
CORS_ALLOW_HEADERS = [
  "authorization",
  "content-type",
]

Example 3: Spring Boot#

Configure CORS in your WebSecurityConfig:

import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 
@Configuration
public class CorsConfig implements WebMvcConfigurer {
  @Override
  public void addCorsMappings(CorsRegistry registry) {
    registry.addMapping("/**") // Apply to all endpoints
      .allowedOrigins("http://localhost:8080") // Vue app origin
      .allowedHeaders("Authorization", "Content-Type") // Allow headers
      .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") // Allow methods
      .allowCredentials(false); // Basic Auth doesn't need cookies
  }
}

3. Handle Preflight Requests (OPTIONS)#

As mentioned earlier, the browser sends an OPTIONS preflight request before your actual GET/POST request. Your server must respond to this OPTIONS request with a 200 OK status and valid CORS headers.

Most modern CORS middlewares (like Express’ cors or Django’s django-cors-headers) handle preflight automatically. If you’re using a custom server setup, explicitly handle OPTIONS:

Example: Manual OPTIONS Handling (Express)#

// Add this BEFORE your API routes
app.options('*', (req, res) => {
  res.setHeader('Access-Control-Allow-Origin', 'http://localhost:8080');
  res.setHeader('Access-Control-Allow-Headers', 'Authorization, Content-Type');
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
  res.sendStatus(200); // Critical: Respond with 200 OK
});

Testing the Solution#

After configuring Axios and the server, verify the fix using these steps:

1. Check Browser DevTools#

  • Open your Vue app and trigger the Axios request.
  • Open Chrome DevTools (F12) → Network tab.
  • Find your API request (e.g., data) and click it.
  • Request Headers: Ensure the Authorization header is present (e.g., Basic YWxpY2U6c2VjdXJlMTIz).
  • Response Headers: Check for CORS headers like Access-Control-Allow-Origin: http://localhost:8080.

2. Test Preflight Requests#

  • In DevTools’ Network tab, look for an OPTIONS request to your API endpoint (it may appear before the actual request).
  • Verify the OPTIONS request returns 200 OK and includes Access-Control-Allow-Headers: Authorization.

3. Use Axios Interceptors (Debugging)#

Add an Axios request interceptor to log headers and ensure they’re sent:

axios.interceptors.request.use(config => {
  console.log('Axios Request Headers:', config.headers);
  return config;
});

Troubleshooting Tips#

If you’re still getting 401, try these fixes:

1. Check Username/Password for Typos#

Double-check that your username and password are correct. Even a missing colon (:) in username:password will break Base64 encoding.

2. Fix Base64 Encoding Issues#

  • Non-ASCII Characters: If your username/password includes non-ASCII characters (e.g., é or ñ), use btoa(unescape(encodeURIComponent(username + ':' + password))) instead of plain btoa (browser-specific).
  • Node.js Environments: If using SSR (e.g., Nuxt.js), use Buffer.from(username + ':' + password).toString('base64') instead of btoa.

3. Verify Server Logs#

Check your server logs to see if:

  • The Authorization header is being received.
  • The preflight OPTIONS request is reaching the server and returning 200 OK.

4. Temporarily Use a CORS Proxy#

As a last resort, use a CORS proxy like https://cors-anywhere.herokuapp.com/ to bypass CORS issues (only for development!):

const apiUrl = 'https://cors-anywhere.herokuapp.com/https://api.example.com/data';
axios.get(apiUrl, { auth: { username: 'alice', password: 'secure123' } });

Conclusion#

Fixing 401 Unauthorized errors with Axios Basic Auth in Vue requires a combination of:

  1. Correctly configuring Axios to send the Authorization header (use the auth option for simplicity).
  2. Ensuring the server returns valid CORS headers (e.g., Access-Control-Allow-Origin, Access-Control-Allow-Headers: Authorization).
  3. Handling preflight OPTIONS requests to unblock the actual request.

By following this guide, you’ll resolve most CORS-related 401 issues and ensure secure, authenticated communication between your Vue app and API.

References#