Refactor code structure and remove redundant changes

This commit is contained in:
pacnpal
2025-11-09 16:31:34 -05:00
parent 2884bc23ce
commit eb68cf40c6
1080 changed files with 27361 additions and 56687 deletions

View File

@@ -0,0 +1,127 @@
# Passkey/WebAuthn Implementation Plan
**Status:** 🟡 In Progress
**Priority:** CRITICAL (Required for Phase 2 Authentication)
**Estimated Time:** 12-16 hours
---
## Overview
Implementing passkey/WebAuthn support to provide modern, passwordless authentication as required by Phase 2 of the authentication migration. This will work alongside existing JWT/password authentication.
---
## Architecture
### Backend (Django)
- **WebAuthn Library:** `webauthn==2.1.0` (already added to requirements)
- **Storage:** PostgreSQL models for storing passkey credentials
- **Integration:** Works with existing JWT authentication system
### Frontend (Next.js)
- **Browser API:** Native WebAuthn API (navigator.credentials)
- **Fallback:** Graceful degradation for unsupported browsers
- **Integration:** Seamless integration with AuthContext
---
## Phase 1: Django Backend Implementation
### 1.1: Database Models
**File:** `django/apps/users/models.py`
```python
class PasskeyCredential(models.Model):
"""
Stores WebAuthn/Passkey credentials for users.
"""
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='passkey_credentials')
# WebAuthn credential data
credential_id = models.TextField(unique=True, db_index=True)
credential_public_key = models.TextField()
sign_count = models.PositiveIntegerField(default=0)
# Metadata
name = models.CharField(max_length=255, help_text="User-friendly name (e.g., 'iPhone 15', 'YubiKey')")
aaguid = models.CharField(max_length=36, blank=True)
transports = models.JSONField(default=list, help_text="Supported transports: ['usb', 'nfc', 'ble', 'internal']")
# Attestation
attestation_object = models.TextField(blank=True)
attestation_client_data = models.TextField(blank=True)
# Tracking
created_at = models.DateTimeField(auto_now_add=True)
last_used_at = models.DateTimeField(null=True, blank=True)
is_active = models.BooleanField(default=True)
class Meta:
db_table = 'users_passkey_credentials'
ordering = ['-created_at']
def __str__(self):
return f"{self.user.email} - {self.name}"
```
### 1.2: Service Layer
**File:** `django/apps/users/services/passkey_service.py`
```python
from webauthn import (
generate_registration_options,
verify_registration_response,
generate_authentication_options,
verify_authentication_response,
options_to_json,
)
from webauthn.helpers.structs import (
AuthenticatorSelectionCriteria,
UserVerificationRequirement,
AuthenticatorAttachment,
ResidentKeyRequirement,
)
class PasskeyService:
"""Service for handling WebAuthn/Passkey operations."""
RP_ID = settings.PASSKEY_RP_ID # e.g., "thrillwiki.com"
RP_NAME = "ThrillWiki"
ORIGIN = settings.PASSKEY_ORIGIN # e.g., "https://thrillwiki.com"
@staticmethod
def generate_registration_options(user: User) -> dict:
"""Generate options for passkey registration."""
@staticmethod
def verify_registration(user: User, credential_data: dict, name: str) -> PasskeyCredential:
"""Verify and store a new passkey credential."""
@staticmethod
def generate_authentication_options(user: User = None) -> dict:
"""Generate options for passkey authentication."""
@staticmethod
def verify_authentication(credential_data: dict) -> User:
"""Verify passkey authentication and return user."""
@staticmethod
def list_credentials(user: User) -> List[PasskeyCredential]:
"""List all passkey credentials for a user."""
@staticmethod
def remove_credential(user: User, credential_id: str) -> bool:
"""Remove a passkey credential."""
```
### 1.3: API Endpoints
**File:** `django/api/v1/endpoints/auth.py` (additions)
```python
# Passkey Registration
@router.post("/passkey/register/options", auth=jwt_auth, response={200: dict})