Vue SDK: Technical Design Document
Executive Summary
@wristband/vue-client-auth is a lightweight, type-safe Vue 3 SDK that bridges frontend and backend authentication systems. It manages secure session initialization, token caching, and metadata synchronization through a cookie-based authentication flow, enabling developers to implement enterprise-grade authentication with minimal boilerplate.
1. Problem Statement
Modern Vue 3 applications require robust authentication handling but face several challenges:
Session Management Complexity
Managing authenticated sessions, tokens, and user metadata across the application requires considerable boilerplate
Token Lifecycle Management
Implementing token caching, expiration detection, and refresh strategies is error-prone
State Consistency
Ensuring consistent authentication state across components and managing side effects is tedious
CSRF Protection
Implementing CSRF token handling for secure API communication requires careful setup
Type Safety
Authentication hooks must provide first-class TypeScript support for custom session metadata
Solution
A composable-first authentication SDK that abstracts these concerns through reactive Vue composables powered by Pinia state management.
2. Architecture Overview
WristbandAuthStore
Pinia Store
- Auth Status Lifecycle
- Session State Management
- Token Management
- Configuration Handling
- Error State Tracking
Composables Layer
Adapter Pattern
- useWristbandStore()
- useWristbandSession()
- useWristbandToken()
- Type-safe generics
- Component-level access
API Client
HTTP Layer
- Fetch-based requests
- CSRF token handling
- Cookie credentials
- Error standardization
- Type-safe responses
Auth Utils
Helper Functions
- URL validation
- Metadata transformation
- Redirect orchestration
- Token expiration detection
- Error handling
3. Key Design Decisions
3.1 Pinia Store Pattern
Decision: Use Pinia's composition API pattern with defineStore('name', () => {...})
Rationale:
- Modularity: Store logic encapsulated in a single function
- Composability: Aligns with Vue 3 Composition API
- Type Safety: Implicit typing from ref/computed return values
- Reactivity: Automatic dependency tracking
- Testability: Pure functions easier to mock
// ✓ Recommended - Composable interface
const { metadata } = useWristbandSession<UserMetadata>()
// ✗ Avoid - Direct store access (not exported)
const store = WristbandAuthStore() // implementation detail
3.2 Token Caching with TTL and Retry Logic
Decision: Implement client-side token caching with 30-second expiration buffer, request deduplication, and exponential backoff retry (3 attempts, 100ms delay)
const tokenRequestRef = ref<Promise<string> | null>(null)
async function getToken(): Promise<string> {
// Return cached token if valid (with 30s buffer)
if (accessToken.value &&
accessTokenExpiresAt.value > Date.now() + 30000) {
return accessToken.value
}
// Deduplicate: return existing request if in-flight
if (tokenRequestRef.value) {
return tokenRequestRef.value
}
// Acquire token with retry logic
tokenRequestRef.value = acquireTokenWithRetry()
return tokenRequestRef.value
}
3.3 CSRF Protection Integration
Decision: Client-side extraction of CSRF token from cookies and injection into request headers
function getCsrfToken(cookieName: string): string | null {
const regex = new RegExp(`(^|;)\s*${cookieName}\s*=\s*([^;]+)`)
const match = document.cookie.match(regex)
return match?.[2] ?? null
}
4. Type Safety & Generics
Custom Session Metadata Typing
Consumers define their session shape via TypeScript generics for full type inference
// Define custom metadata structure
interface UserSession {
firstName: string
lastName: string
email: string
permissions: string[]
accountType: 'free' | 'pro' | 'enterprise'
}
// Typed composable usage
export default function Dashboard() {
const { metadata, userId } = useWristbandSession<UserSession>()
// Full type inference
const displayName = `${metadata.value.firstName} ${metadata.value.lastName}`
const isPro = metadata.value.accountType === 'pro'
}
5. Performance & Security
Performance Optimizations
- Token caching eliminates 90%+ endpoint requests
- Request deduplication prevents concurrent token acquisition
- Lazy config validation reduces initialization overhead
- O(1) CSRF token extraction, no DOM traversal
Security Features
- HttpOnly, Secure session cookies with SameSite=Strict
- CSRF token extraction and header injection
- Token expiration with 30-second safety buffer
- Bearer token scheme for authenticated requests
Appendix: File Structure
src/
├── api/
│ ├── api-client.ts # Fetch-based HTTP client with CSRF
│ └── api-client.test.ts # Client unit tests
├── composables/
│ ├── useWristbandAuthStore.ts # Store access & config
│ ├── useWristbandSession.ts # Session data access
│ ├── useWristbandToken.ts # Token acquisition
│ └── *.test.ts # Composable tests
├── stores/
│ └── wristband.ts # Pinia store: main auth state
├── types/
│ ├── auth-store.ts # Core type definitions
│ ├── api-client-types.ts # HTTP types
│ ├── auth-utils-types.ts # Utility types
│ └── errors.ts # Error codes enum
├── utils/
│ ├── api-client-utils.ts # CSRF token extraction
│ ├── auth-store-utils.ts # URL validation, helpers
│ ├── auth-utils.ts # Redirect utilities
│ └── *.test.ts # Utility tests
├── error.ts # Error class definitions
└── index.ts # Public exports (entry point)Explore the Full Implementation
View the complete source code, examples, and contribute to the open source project.