User Signup Flow¶
This document outlines the user signup flow for OmniButler.
System Flow¶
```mermaid sequenceDiagram participant User participant Frontend participant Firebase Auth participant Backend participant Firestore participant Turso
User->>Frontend: Sign in with Google
Frontend->>Firebase Auth: Authenticate
Firebase Auth-->>Frontend: Return Firebase Token
Frontend->>Backend: Request API Access (with token)
Backend->>Firebase Auth: Verify Token
Firebase Auth-->>Backend: Token Verified
Backend->>Firestore: Check for Existing User
alt User Exists
Firestore-->>Backend: Return Existing User
else New User
Backend->>Turso: Create User Database
Turso-->>Backend: Database Created
Backend->>Firestore: Create New User Record
Firestore-->>Backend: User Created
end
Backend-->>Frontend: Return User Data
```
Implementation Details¶
Once a user signs up through the Google OAuth flow, we:
- Authenticate with Firebase
- Create a database instance for the user
- Store user metadata in Firestore
- Configure default settings
- Return the user profile
Code Flow¶
```mermaid graph TD subgraph Frontend A[User Sign In] → B[Firebase Auth SDK] B → C[Get Firebase Token] end
subgraph Backend
D[API Request with Token] --> E[Auth Middleware]
E --> F[verify_firebase_token]
subgraph Application Layer
F --> G[FirestoreAppUserRepository]
G --> H[find_by_provider_user_id]
end
subgraph Domain Layer
H --> I[AppUser Model]
I --> J[DatabaseInfo Model]
end
subgraph Infrastructure Layer
J --> K[TursoAdminClient]
K --> L[create_database]
K --> M[create_database_token]
G --> N[Firestore Operations]
end
end
style Frontend fill:#f9f,stroke:#333,stroke-width:2px
style Backend fill:#bbf,stroke:#333,stroke-width:2px
style Application Layer fill:#dfd,stroke:#333,stroke-width:2px
style Domain Layer fill:#fdd,stroke:#333,stroke-width:2px
style Infrastructure Layer fill:#ddf,stroke:#333,stroke-width:2px
```
Key Components¶
- Frontend
- Firebase Auth SDK
- Token management
-
API client
-
Application Layer
FirestoreAppUserRepository: Manages user data persistenceverify_firebase_token: Handles token verification-
API routes and controllers
-
Domain Layer
AppUser: Core user entityDatabaseInfo: Database connection details-
ProviderUser: External provider user data -
Infrastructure Layer
TursoAdminClient: Database management- Firestore client
- Firebase admin SDK
Technical Details¶
Authentication Flow¶
- Initial Authentication
- User signs in through Google OAuth
- Firebase Authentication generates a JWT token
-
Token includes user details (name, email, provider ID)
-
Token Verification
- Backend verifies the Firebase token
-
Extracts user information:
uid: Firebase user IDemail: User's email addressname: User's display nameprovider_name: Authentication provider (e.g., "google.com")
-
User Creation/Retrieval
- System checks for existing user using provider ID
- If new user:
- Creates unique
appUserId - Initializes user database in Turso
- Creates Firestore user record
- Creates unique
- If existing user:
- Retrieves user data
- Updates provider information if needed
Data Models¶
AppUser¶
interface AppUser {
appUserId: string;
names: string[];
providerUserIds: {
[provider: string]: string[];
};
database_info?: {
access_token: string;
name: string;
};
userBankAccounts: {
[bankId: string]: string[];
};
}
ProviderUser¶
interface ProviderUser {
displayName: string;
tokens: AuthTokens[];
scopes: string[];
}
interface AuthTokens {
accessToken: string;
refreshToken: string;
}
Database Setup¶
For each new user, the system: 1. Creates a dedicated Turso database 2. Generates an access token for the database 3. Stores database connection info in the user's Firestore record
Security Considerations¶
- All authentication is handled through Firebase
- Database access tokens are securely stored
- Provider tokens are encrypted
- Each user has isolated database access
API Endpoints¶
The signup flow primarily uses these endpoints:
- Firebase Authentication
- Handles OAuth flow
- Manages user sessions
-
Provides JWT tokens
-
Backend Authentication
/api/v1/auth/verify- Token verification- Internal user creation endpoints
Error Handling¶
The system handles various error scenarios:
- Authentication Failures
- Invalid tokens
- Expired sessions
-
Provider errors
-
Database Creation Failures
- Turso connection issues
- Duplicate user detection
-
Storage failures
-
Provider Integration Issues
- OAuth errors
- Token refresh failures
- Scope permission issues
Monitoring¶
The system logs key events: - User creation - Database initialization - Authentication attempts - Error conditions
Future Enhancements¶
Planned improvements: 1. Support for additional authentication providers 2. Enhanced error recovery 3. Improved monitoring and analytics 4. Additional security features
Areas for Improvement¶
By Category¶
1. Security Enhancements¶
- Token Handling
- Implement proper Authorization header validation
- Add rate limiting for token verification attempts
- Implement token revocation mechanism
- Add token expiration checks
-
Remove sensitive data from debug logs
-
Database Security
- Remove hardcoded development tokens
- Implement encryption for sensitive data in Firestore
- Add database access audit logging
-
Implement row-level security in Turso
-
Error Handling
- Implement specific error types for different failure scenarios
- Add proper error messages without exposing sensitive information
- Implement consistent error handling patterns
2. Architecture Improvements¶
- Clean Architecture
- Create proper interfaces for authentication providers
- Move Firebase Admin SDK dependency to infrastructure layer
- Separate authentication and authorization concerns
-
Implement proper dependency injection
-
Repository Pattern
- Define clear repository interfaces
- Implement proper abstraction for data access
- Separate concerns in AppUserRepository
-
Add proper transaction handling
-
Service Layer
- Create provider-agnostic token management
- Implement proper service interfaces
- Add proper error handling in services
- Implement proper validation
3. Code Quality¶
- Error Handling
- Standardize error handling patterns
- Implement proper error types
- Add proper error context
-
Implement proper error logging
-
Logging
- Implement structured logging
- Remove sensitive data from logs
- Standardize log levels
-
Add proper log context
-
Type Safety
- Add proper type hints
- Implement proper validation
- Use Pydantic models consistently
- Add proper type checking
4. Performance¶
- Database Operations
- Implement caching strategy
- Add proper batching for database operations
- Implement pagination
-
Add proper indexing
-
Token Management
- Implement token caching
- Add proper token refresh mechanism
- Implement proper token storage
- Add proper token validation
By Priority¶
Critical (Security & Data Integrity)¶
- Remove hardcoded development tokens
- Implement proper Authorization header validation
- Add encryption for sensitive data in Firestore
- Implement proper error handling without sensitive data exposure
- Add proper token revocation mechanism
High (Architecture & Scalability)¶
- Create proper interfaces for authentication providers
- Implement proper repository interfaces
- Add proper transaction handling
- Implement proper caching strategy
- Add proper batching for database operations
Medium (Code Quality & Maintainability)¶
- Standardize error handling patterns
- Implement structured logging
- Add proper type hints
- Implement proper validation
- Add proper documentation
Low (Performance & Optimization)¶
- Implement token caching
- Add proper indexing
- Implement pagination
- Add proper batching
- Implement proper caching
Implementation Notes¶
Security Enhancements¶
# Example of improved token handling
def get_token_from_request(request: Request) -> str | None:
auth_header = request.headers.get("Authorization")
if not auth_header or not auth_header.startswith("Bearer "):
return None
return auth_header.split(" ")[1]
# Example of proper error handling
class AuthenticationError(Exception):
pass
class TokenExpiredError(AuthenticationError):
pass
@app.exception_handler(AuthenticationError)
async def auth_error_handler(request: Request, exc: AuthenticationError):
return JSONResponse(
status_code=401,
content={"detail": str(exc)}
)
Architecture Improvements¶
# Example of proper interface definition
class AuthProvider(ABC):
@abstractmethod
def verify_token(self, token: str) -> UserIdentity:
pass
@abstractmethod
def refresh_token(self, refresh_token: str) -> TokenPair:
pass
# Example of proper repository interface
class AppUserRepository(ABC):
@abstractmethod
def find_by_provider_id(self, provider_id: str, provider: str) -> AppUser | None:
pass
@abstractmethod
def create(self, user: AppUser) -> None:
pass
Performance Optimizations¶
# Example of caching implementation
class TokenCache:
def __init__(self, redis_client: Redis):
self.redis = redis_client
async def get_token(self, key: str) -> str | None:
return await self.redis.get(key)
async def set_token(self, key: str, token: str, ttl: int):
await self.redis.setex(key, ttl, token)
Each improvement should be tracked in the project's issue tracker and implemented with proper testing and documentation. The priority order should be adjusted based on specific project needs and security requirements.