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>
This commit is contained in:
padreug 2025-09-07 00:53:42 +02:00
parent 4feb5459cc
commit 6cb10a31db
3 changed files with 311 additions and 11 deletions

View file

@ -0,0 +1,235 @@
# 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

View file

@ -24,14 +24,15 @@ A Vue component that provides the chat interface with:
- Encrypted message exchange
- Connection status indicators
### 2. useNostrChat.ts
**Location**: `src/composables/useNostrChat.ts`
### 2. ChatService
**Location**: `src/modules/chat/services/chat-service.ts`
A composable that handles:
- Nostr relay connections
A service-based architecture that handles:
- Nostr relay connections via dependency injection
- Message encryption/decryption
- User authentication with LNBits
- User authentication through AuthService
- Real-time message subscription
- Integration with modular service architecture
### 3. ChatPage.vue
**Location**: `src/pages/ChatPage.vue`
@ -83,9 +84,10 @@ Response:
## Features
### 1. User Integration
- Automatically loads peers from LNBits user database
- Uses existing `pubkey` and `prvkey` fields
- Admin-only access to private keys for messaging
- Automatically loads peers from LNBits user database via dependency injection
- Uses existing `pubkey` and `prvkey` fields from AuthService
- Authentication managed through centralized AuthService
- No dual authentication issues - single source of truth
### 2. Nostr Relay Integration
- Connects to multiple Nostr relays for redundancy

View file

@ -78,11 +78,74 @@ The application uses the following LNBits API endpoints:
- Route protection for authenticated pages
- Secure logout with token cleanup
## Migration from Nostr
## Architecture
The following components have been removed or replaced:
The authentication system uses a **dependency injection pattern** for clean modular architecture:
- `useIdentity.ts``useAuth.ts`
### Core Components
1. **AuthService** (`src/modules/base/auth/auth-service.ts`)
- Singleton service that manages authentication state
- Handles API calls to LNBits
- Provides reactive state management
2. **useAuthService** (`src/composables/useAuthService.ts`)
- Wrapper composable that provides unified access to AuthService
- Uses dependency injection to access the service
- Provides consistent API for all components
3. **Dependency Injection Container** (`src/core/di-container.ts`)
- Manages service registration and injection
- Ensures single source of truth across modules
### Usage Pattern
Components access authentication through the `useAuth()` composable:
```typescript
import { useAuth } from '@/composables/useAuthService'
export default defineComponent({
setup() {
const auth = useAuth()
// Access authentication state
const isAuthenticated = auth.isAuthenticated
const currentUser = auth.currentUser
// Call authentication methods
const login = (credentials) => auth.login(credentials)
const logout = () => auth.logout()
return {
isAuthenticated,
currentUser,
login,
logout
}
}
})
```
### Service Registration
The AuthService is registered in the base module and made available through dependency injection:
```typescript
// In base module
container.provide(SERVICE_TOKENS.AUTH_SERVICE, authService)
// In components
const authService = injectService(SERVICE_TOKENS.AUTH_SERVICE)
```
## Migration from Legacy Architecture
The following components have been updated:
- **Legacy**: Global `useAuth.ts` composable → **Current**: `useAuthService.ts` with dependency injection
- **Legacy**: Direct service imports → **Current**: Dependency injection pattern
- **Legacy**: Dual authentication detection → **Current**: Single source of truth via AuthService
- `IdentityDialog.vue``LoginDialog.vue`
- `PasswordDialog.vue` → Integrated into `LoginDialog.vue`
- Nostr connection status → User authentication status