Getting Started with Nuxt Bearer Auth

Learn how to install, configure, and secure your Nuxt application with server-side bearer authentication.

Overview & Getting Started Nuxt 4 / TypeScript

Introduction

nuxt-bearer-auth provides a server-side authentication layer between your Nuxt application and any external bearer-token API (e.g. Laravel Sanctum, FastAPI, Django REST Framework, Node.js, Go). Instead of storing bearer tokens in the browser's localStorage or cookies where they can be intercepted or exposed to client-side scripts, nuxt-bearer-auth holds the bearer token securely on the Nuxt server inside a Redis store and hands the browser an HTTP-only session cookie.
typescript
┌───────────────┐     HTTP-only Session Cookie     ┌────────────────┐     Bearer Token     ┌────────────────┐
│    Browser    │ ◄──────────────────────────────► │  Nuxt Server   │ ◄──────────────────► │  External API  │
└───────────────┘                                  └───────┬────────┘                      └────────────────┘
                                                           │
                                                           ▼
                                                   ┌────────────────┐
                                                   │  Redis Store   │
                                                   │ (Server Session)│
                                                   └────────────────┘

Requirements

Before installing the module, ensure your environment meets the following:

  • Nuxt: ^3.12.0 || ^4.0.0 (the module's declared peer dependency range)
  • Node.js: Use a version supported by the Nuxt release in your project; Nuxt's Node.js requirements differ by release.
  • Redis Server: A running Redis 6+ or Redis 7+ instance (local or hosted e.g. Upstash, AWS ElastiCache, Redis Cloud)
  • Compatibility & Verification

    The module declares the Nuxt peer range ^3.12.0 || ^4.0.0. Compatibility checks cover representative releases, not every version in that range. The module repository's consumer compatibility workflow builds and packs the current module, installs that package into an isolated consumer fixture, and runs Nuxt preparation and a production build.

    The automated matrix targets Nuxt 3.12.0, 3.21.11, and 4.6.1 on Node.js 24.19.0 with npm 10.0.0. Nuxt 3.21.11 and 4.6.0 have been manually verified with consumer preparation and production builds. Nuxt 3.12.0 and 4.6.1 remain unverified until their CI jobs succeed. Nuxt 5 compatibility has not been established. Check the workflow for current results; its configuration alone does not mean a run has passed.

    Installation

    Install nuxt-bearer-auth, redis client, and nuxt-csurf (for CSRF protection) using your package manager:
    bash
    # Using npm
    npm install nuxt-bearer-auth redis nuxt-csurf
    
    # Using pnpm
    pnpm add nuxt-bearer-auth redis nuxt-csurf
    
    # Using yarn
    yarn add nuxt-bearer-auth redis nuxt-csurf
    

    Nuxt Configuration

    Add nuxt-bearer-auth to your nuxt.config.ts modules array and configure the API base URL and Redis connection:
    typescript
    // nuxt.config.ts
    export default defineNuxtConfig({
      modules: ['nuxt-bearer-auth'],
    
      bearerAuth: {
        apiBaseUrl: process.env.API_BASE_URL,
        redisUrl: process.env.REDIS_URL || 'redis://127.0.0.1:6379',
    
        redirects: {
          login: '/login',
          authenticated: '/dashboard',
          logout: '/',
          unauthorized: '/auth/not-allowed',
        },
    
        routes: {
          public: ['/', '/login', '/forgot-password', '/reset-password'],
          authPages: ['/login', '/forgot-password', '/reset-password'],
        },
      },
    })
    

    Environment Variables

    Create or update your .env file with your backend and Redis credentials:
    bash
    # .env
    API_BASE_URL=https://api.example.com
    REDIS_URL=redis://127.0.0.1:6379
    APP_ENV=local
    
    Security Tip: In production, ensure REDIS_URL uses password authentication or TLS (rediss://...) and is isolated within your private VPC network. Redis holds live session data including bearer tokens — treat it as sensitive infrastructure.

    Your First Login

    In your Vue component or page (e.g. pages/login.vue), import and use the useBearerAuth() composable:
    vue
    <script setup lang="ts">
    const auth = useBearerAuth()
    const email = ref('')
    const password = ref('')
    const errorMessage = ref('')
    const isSubmitting = ref(false)
    
    async function handleLogin() {
      isSubmitting.value = true
      errorMessage.value = ''
    
      try {
        // Calls /api/auth/login -> authenticates with backend -> stores token in Redis -> sets session cookie
        await auth.login({
          email: email.value, // accepts email, username, phone, mobile, or identifier
          password: password.value,
        })
        // Upon success, user is automatically redirected to redirects.authenticated ('/dashboard')
      } catch (err: any) {
        errorMessage.value = err?.data?.message || auth.error.value || 'Invalid credentials'
      } finally {
        isSubmitting.value = false
      }
    }
    </script>
    
    <template>
      <div class="login-container">
        <h1>Sign In</h1>
        <form @submit.prevent="handleLogin">
          <div v-if="errorMessage" class="error-banner">{{ errorMessage }}</div>
    
          <label>Email Address</label>
          <input v-model="email" type="email" required autocomplete="email" />
    
          <label>Password</label>
          <input v-model="password" type="password" required autocomplete="current-password" />
    
          <button type="submit" :disabled="isSubmitting || auth.loading.value">
            {{ isSubmitting ? 'Signing in...' : 'Sign In' }}
          </button>
        </form>
      </div>
    </template>
    

    Protecting Routes

    By default, nuxt-bearer-auth installs a global client and server route middleware. 1. Any route in routes.public is accessible to unauthenticated visitors. 2. Any route not listed in routes.public automatically redirects unauthenticated visitors to redirects.login (e.g. /login?redirect=/dashboard). 3. If an authenticated user visits an auth page (listed in routes.authPages such as /login), they are redirected to redirects.authenticated.
    typescript
    // Customizing route protection rules
    bearerAuth: {
      routes: {
        public: ['/', '/about', '/pricing', '/login'],
        authPages: ['/login', '/register'],
      }
    }
    

    Next Steps

  • Explore Configuration Reference to customize endpoints, cookies, and response paths.
  • Read Authentication Flows to implement OTP verification, Social Auth, and Token Refresh.
  • Learn about SSR & Hydration to understand how session state is rendered on the server.