Implements complete authentication system using Supabase Auth SDK following Archon's vertical slice architecture. Frontend Changes: - Install @supabase/supabase-js dependency - Create auth feature in vertical slice pattern: * AuthContext and Provider for global auth state * authService with Supabase Auth methods (signIn, signUp, signOut, etc.) * Auth query hooks with TanStack Query integration * TypeScript types for User, Session, AuthState * ProtectedRoute component for route guards - Add LoginPage and SignUpPage with Tron-themed design - Update App.tsx with AuthProvider and protected routes - Configure Supabase client with environment variables Backend Changes: - Create auth_service.py for JWT token validation - Create auth_middleware.py for protecting API routes (optional, commented by default) - Create auth_api.py with endpoints: * POST /api/auth/verify - Verify JWT token * GET /api/auth/user - Get current user * GET /api/auth/health - Auth service health check - Register auth router in main.py - Add middleware configuration (disabled by default) Configuration: - Update .env.example with VITE_SUPABASE_URL and VITE_SUPABASE_ANON_KEY - Add comprehensive AUTHENTICATION_SETUP.md documentation Features: - Email/password authentication - Persistent sessions with localStorage - Auto token refresh - Route protection with loading states - Integration with existing TanStack Query patterns - Optional backend middleware for API protection - Row Level Security (RLS) ready Architecture follows CLAUDE.md guidelines: - Vertical slice architecture for auth feature - TanStack Query for state management - No backwards compatibility needed (beta) - KISS principle - Fail fast with detailed errors Notes: - Auth middleware is commented out by default to avoid breaking existing installations - Users can enable it when ready by uncommenting in main.py - Frontend auth works independently of backend middleware - Comprehensive setup guide included in AUTHENTICATION_SETUP.md
76 lines
2.0 KiB
Python
76 lines
2.0 KiB
Python
"""
|
|
Authentication API endpoints.
|
|
|
|
Provides endpoints for token verification and user information.
|
|
Note: Login/signup/logout are handled client-side by Supabase Auth SDK.
|
|
"""
|
|
|
|
from fastapi import APIRouter, HTTPException, Request
|
|
from pydantic import BaseModel
|
|
|
|
from ..services.auth_service import auth_service
|
|
|
|
router = APIRouter(prefix="/api/auth", tags=["authentication"])
|
|
|
|
|
|
class TokenVerifyRequest(BaseModel):
|
|
"""Request model for token verification."""
|
|
|
|
token: str
|
|
|
|
|
|
class TokenVerifyResponse(BaseModel):
|
|
"""Response model for token verification."""
|
|
|
|
valid: bool
|
|
user: dict | None = None
|
|
|
|
|
|
class UserResponse(BaseModel):
|
|
"""Response model for user information."""
|
|
|
|
id: str
|
|
email: str
|
|
user_metadata: dict
|
|
app_metadata: dict
|
|
|
|
|
|
@router.post("/verify", response_model=TokenVerifyResponse)
|
|
async def verify_token(request: TokenVerifyRequest):
|
|
"""
|
|
Verify a JWT token and return user information.
|
|
|
|
This endpoint is public and does not require authentication.
|
|
It's used to validate tokens from the frontend.
|
|
"""
|
|
try:
|
|
user = await auth_service.verify_token(request.token)
|
|
return TokenVerifyResponse(valid=True, user=user)
|
|
except HTTPException:
|
|
return TokenVerifyResponse(valid=False, user=None)
|
|
|
|
|
|
@router.get("/user", response_model=UserResponse)
|
|
async def get_current_user(request: Request):
|
|
"""
|
|
Get information about the currently authenticated user.
|
|
|
|
Requires valid JWT token in Authorization header.
|
|
"""
|
|
if not hasattr(request.state, "user"):
|
|
raise HTTPException(status_code=401, detail="Not authenticated")
|
|
|
|
user = request.state.user
|
|
return UserResponse(
|
|
id=user["id"],
|
|
email=user["email"],
|
|
user_metadata=user.get("user_metadata", {}),
|
|
app_metadata=user.get("app_metadata", {}),
|
|
)
|
|
|
|
|
|
@router.get("/health")
|
|
async def auth_health():
|
|
"""Health check endpoint for authentication service."""
|
|
return {"status": "healthy", "service": "auth"}
|