web-app/docs/01-architecture/authentication-architecture.md
padreug 6cb10a31db Update documentation to reflect new authentication architecture
Remove legacy references to global auth composable and document the new
dependency injection pattern with single source of truth.

Key Documentation Updates:
• Update authentication.md with DI architecture details and usage patterns
• Update chat integration docs to reference AuthService and remove legacy patterns
• Add comprehensive authentication-architecture.md with full technical details
• Document migration path from legacy global auth to current DI pattern

Content Changes:
• Replace useAuth.ts references with useAuthService.ts
• Document AuthService as singleton with dependency injection
• Add code examples for both component and service usage
• Explain benefits of new architecture (single source of truth, no timing issues)
• Update chat integration to reflect service-based architecture

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-07 00:53:42 +02:00

235 lines
No EOL
7 KiB
Markdown

# Authentication Architecture
This document describes the current authentication architecture using dependency injection and service-based patterns.
## Overview
The authentication system has been refactored from a legacy global composable approach to a modern dependency injection pattern. This eliminates timing issues, improves maintainability, and provides a single source of truth for authentication state.
## Architecture Components
### 1. AuthService (Core Service)
**Location**: `src/modules/base/auth/auth-service.ts`
The `AuthService` is a singleton service that extends `BaseService` and provides:
- Reactive authentication state management
- LNBits API integration
- Event-driven authentication lifecycle
- Automatic token management
**Key Features**:
```typescript
export class AuthService extends BaseService {
// Public reactive state
public isAuthenticated = ref(false)
public user = ref<User | null>(null)
public isLoading = ref(false)
public error = ref<Error | null>(null)
// Computed properties for compatibility
public currentUser = computed(() => this.user.value)
public userDisplay = computed(() => { /* user display logic */ })
// Methods
async login(credentials: LoginCredentials): Promise<void>
async register(data: RegisterData): Promise<void>
async logout(): Promise<void>
async checkAuth(): Promise<boolean>
async updatePassword(current: string, newPass: string): Promise<void>
async updateProfile(data: Partial<User>): Promise<void>
}
```
### 2. useAuthService Composable (API Layer)
**Location**: `src/composables/useAuthService.ts`
The `useAuthService` composable provides a clean, unified API that bridges Vue components with the injected AuthService:
```typescript
export function useAuth() {
const authService = injectService(SERVICE_TOKENS.AUTH_SERVICE) as AuthService
return {
// State (reactive refs from service)
currentUser: authService.currentUser,
isAuthenticated: authService.isAuthenticated,
isLoading: authService.isLoading,
error: authService.error,
userDisplay: authService.userDisplay,
// Methods (delegated to service)
initialize: () => authService.initialize(),
login: (credentials: any) => authService.login(credentials),
register: (data: any) => authService.register(data),
logout: () => authService.logout(),
checkAuth: () => authService.checkAuth()
}
}
```
### 3. Dependency Injection Container
**Location**: `src/core/di-container.ts`
The DI container manages service registration and injection:
```typescript
// Service registration (in base module)
container.provide(SERVICE_TOKENS.AUTH_SERVICE, authService)
// Service consumption (in components/other services)
const authService = injectService(SERVICE_TOKENS.AUTH_SERVICE) as AuthService
```
## Usage Patterns
### In Vue Components (Recommended)
```vue
<script setup lang="ts">
import { useAuth } from '@/composables/useAuthService'
const auth = useAuth()
// Access reactive state
const isAuthenticated = auth.isAuthenticated
const currentUser = auth.currentUser
// Call methods
const handleLogin = async (credentials) => {
await auth.login(credentials)
}
</script>
```
### In Services (Direct Injection)
```typescript
import { injectService, SERVICE_TOKENS } from '@/core/di-container'
import type { AuthService } from '@/modules/base/auth/auth-service'
export class SomeService extends BaseService {
private get authService(): AuthService {
return this.dependencies.get('AuthService') as AuthService
}
async someMethod() {
const user = this.authService.user.value
if (user?.pubkey) {
// Use authenticated user data
}
}
}
```
## Benefits of New Architecture
### 1. **Single Source of Truth**
- All authentication state managed by AuthService singleton
- No more timing issues between global and injected auth
- Consistent state across all modules and components
### 2. **Dependency Injection Benefits**
- Loose coupling between components and auth logic
- Easy to test (can inject mock services)
- Modular architecture with clear boundaries
- Service lifecycle management
### 3. **Improved Maintainability**
- Centralized authentication logic
- Event-driven architecture for auth state changes
- Clear separation of concerns
- Eliminated complex dual-auth detection patterns
### 4. **Performance Improvements**
- No duplicate service instances
- Efficient reactive state management
- Reduced complexity in components
## Migration Guide
### Before (Legacy Pattern)
```typescript
// ❌ Old global composable pattern
import { auth } from '@/composables/useAuth'
// Direct access to global singleton
const isAuthenticated = auth.isAuthenticated.value
```
### After (Current Pattern)
```typescript
// ✅ New dependency injection pattern
import { useAuth } from '@/composables/useAuthService'
const auth = useAuth()
const isAuthenticated = auth.isAuthenticated.value
```
## Service Integration
### Module Registration
Each module that needs authentication access should:
1. **Declare dependency** on AuthService in module metadata
2. **Access via dependency injection** using the DI container
3. **Use reactive state** from the service for UI updates
### Example Service Integration
```typescript
export class ChatService extends BaseService {
protected readonly metadata = {
name: 'ChatService',
dependencies: ['AuthService'] // Declare dependency
}
async sendMessage(content: string) {
// Access auth through DI
const user = this.authService.user.value
if (!user?.pubkey || !user?.prvkey) {
throw new Error('Authentication required for messaging')
}
// Use authenticated user data
const encrypted = await nip04.encrypt(user.prvkey, recipientPubkey, content)
// ... rest of implementation
}
}
```
## Error Handling
The authentication system provides comprehensive error handling:
1. **Network Errors**: Handled in AuthService with proper error propagation
2. **Invalid Credentials**: Clear error messages passed to components
3. **Token Expiration**: Automatic logout with cleanup
4. **Service Unavailable**: Graceful degradation with retry logic
## Testing
The dependency injection architecture makes testing straightforward:
```typescript
// Mock the auth service for testing
const mockAuthService = {
isAuthenticated: ref(true),
currentUser: ref({ id: 'test-user', username: 'test' }),
login: vi.fn(),
logout: vi.fn()
}
// Inject mock in tests
container.provide(SERVICE_TOKENS.AUTH_SERVICE, mockAuthService)
```
## Security Considerations
1. **Token Storage**: Secure storage in localStorage with automatic cleanup
2. **API Integration**: All requests authenticated via LNBits tokens
3. **State Management**: Reactive state prevents stale authentication data
4. **Service Isolation**: Authentication logic isolated in dedicated service
## Future Enhancements
1. **Token Refresh**: Automatic token refresh before expiration
2. **Multi-Factor Authentication**: Support for additional auth factors
3. **Session Management**: Enhanced session handling and persistence
4. **Audit Logging**: Authentication event logging for security