youtube-summarizer/docs/stories/3.1.user-authentication-sys...

12 KiB

Story 3.1: User Authentication System

Status

Complete

Story

As a user
I want to create an account and login
So that I can access my summary history across devices and have a personalized experience

Acceptance Criteria

  1. Email/password registration with verification email
  2. Secure password requirements enforced (minimum 8 characters, complexity rules)
  3. JWT-based authentication with refresh tokens
  4. Password reset functionality via email
  5. Optional OAuth integration with Google for single sign-on
  6. Session management with automatic logout after inactivity

Tasks / Subtasks

  • Task 1: Database Schema and Models (AC: 1, 2, 3, 6)

    • Install authentication dependencies (python-jose, passlib, email-validator)
    • Create User model with email, password_hash, is_verified fields
    • Create RefreshToken model for JWT refresh token storage
    • Create APIKey model for future API access
    • Initialize Alembic and create initial migration
  • Task 2: JWT Authentication Service (AC: 3, 6)

    • Implement JWT token generation (access + refresh tokens)
    • Create token verification and decoding functions
    • Implement refresh token rotation mechanism
    • Add session timeout configuration (default 30 minutes)
    • Create authentication dependency for protected routes
  • Task 3: User Registration System (AC: 1, 2)

    • Create POST /api/auth/register endpoint
    • Implement password validation (min 8 chars, 1 upper, 1 lower, 1 number)
    • Hash passwords using bcrypt with salt
    • Generate email verification token
    • Send verification email on registration
  • Task 4: Email Service (AC: 1, 4)

    • Configure SMTP settings (use MailHog for development)
    • Create email templates for verification and password reset
    • Implement async email sending with aiosmtplib
    • Add email queue for retry on failure
    • Create email verification endpoint
  • Task 5: Login and Session Management (AC: 3, 6)

    • Create POST /api/auth/login endpoint
    • Validate credentials and return JWT tokens
    • Implement refresh token endpoint
    • Create logout endpoint with token revocation
    • Add session activity tracking for auto-logout
  • Task 6: Password Reset Flow (AC: 4)

    • Create password reset request endpoint
    • Generate secure reset token with expiration
    • Send password reset email
    • Create password reset confirmation endpoint
    • Invalidate reset token after use
  • Task 7: Frontend Authentication Context (AC: 3, 6)

    • Create AuthContext with JWT token management
    • Implement useAuth hook for auth state
    • Add automatic token refresh on 401 responses
    • Create protected route wrapper component
    • Handle session timeout in UI
  • Task 8: Frontend Authentication Components (AC: 1, 2, 4)

    • Build LoginForm component with validation
    • Create RegisterForm with password strength indicator
    • Implement ForgotPasswordForm component
    • Add EmailVerification handler component
    • Create UserMenu dropdown for authenticated users
  • Task 9: Authentication Pages (AC: 1, 4, 5)

    • Create login page with form and OAuth option placeholder
    • Build registration page with terms acceptance
    • Implement forgot password page
    • Create email verification landing page
    • Add password reset confirmation page
  • Task 10: OAuth Google Integration (AC: 5) - Future Enhancement

    • Configure Google OAuth2 credentials
    • Implement OAuth flow endpoints
    • Add Google login button to UI
    • Handle OAuth callback and user creation
    • Link OAuth accounts to existing users
  • Task 11: Security and Testing (AC: 2, 3, 6)

    • Add rate limiting for auth endpoints (5 attempts per minute) - via middleware
    • Implement CSRF protection for state-changing operations - via JWT
    • Write unit tests for auth service (>80% coverage)
    • Create integration tests for all auth endpoints
    • Add E2E tests for complete auth flows - Future when frontend ready

Dev Notes

Architecture Context

This story introduces user authentication to transform the YouTube Summarizer from an anonymous tool to a personalized platform. The authentication system follows JWT best practices with short-lived access tokens (15 minutes) and longer refresh tokens (7 days) stored securely.

Database Schema

[Source: Epic 3 - User Model]

# backend/models/user.py
from sqlalchemy import Column, String, Boolean, DateTime, ForeignKey
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.orm import relationship
import uuid
from datetime import datetime

class User(Base):
    __tablename__ = "users"
    
    id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    email = Column(String(255), unique=True, nullable=False, index=True)
    password_hash = Column(String(255), nullable=False)
    is_verified = Column(Boolean, default=False)
    is_active = Column(Boolean, default=True)
    created_at = Column(DateTime, default=datetime.utcnow)
    updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
    last_login = Column(DateTime)
    
    # Relationships
    refresh_tokens = relationship("RefreshToken", back_populates="user", cascade="all, delete-orphan")
    summaries = relationship("Summary", back_populates="user")
    api_keys = relationship("APIKey", back_populates="user")
    
class RefreshToken(Base):
    __tablename__ = "refresh_tokens"
    
    id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    user_id = Column(UUID(as_uuid=True), ForeignKey("users.id"), nullable=False)
    token_hash = Column(String(255), unique=True, nullable=False, index=True)
    expires_at = Column(DateTime, nullable=False)
    revoked = Column(Boolean, default=False)
    created_at = Column(DateTime, default=datetime.utcnow)
    
    user = relationship("User", back_populates="refresh_tokens")

JWT Configuration

[Source: docs/architecture.md#security]

# backend/core/config.py additions
class AuthSettings(BaseSettings):
    JWT_SECRET_KEY: str = Field(..., env="JWT_SECRET_KEY")  # Generate with: openssl rand -hex 32
    JWT_ALGORITHM: str = "HS256"
    ACCESS_TOKEN_EXPIRE_MINUTES: int = 15
    REFRESH_TOKEN_EXPIRE_DAYS: int = 7
    EMAIL_VERIFICATION_EXPIRE_HOURS: int = 24
    PASSWORD_RESET_EXPIRE_MINUTES: int = 30
    
    # Email settings
    SMTP_HOST: str = Field("localhost", env="SMTP_HOST")
    SMTP_PORT: int = Field(1025, env="SMTP_PORT")  # MailHog default
    SMTP_USER: Optional[str] = Field(None, env="SMTP_USER")
    SMTP_PASSWORD: Optional[str] = Field(None, env="SMTP_PASSWORD")
    SMTP_FROM_EMAIL: str = Field("noreply@youtube-summarizer.local", env="SMTP_FROM_EMAIL")

API Endpoint Structure

All authentication endpoints follow RESTful conventions under /api/auth/:

POST   /api/auth/register         - Create new user account
POST   /api/auth/login           - Authenticate and receive tokens
POST   /api/auth/refresh         - Refresh access token
POST   /api/auth/logout          - Revoke refresh token
POST   /api/auth/verify-email    - Verify email with token
POST   /api/auth/resend-verification - Resend verification email
POST   /api/auth/reset-password  - Request password reset
POST   /api/auth/reset-password/confirm - Confirm password reset
GET    /api/auth/me             - Get current user profile (protected)

Frontend Authentication Flow

The frontend uses React Context API for auth state management with automatic token refresh:

// frontend/src/contexts/AuthContext.tsx
interface AuthContextType {
  user: User | null;
  isAuthenticated: boolean;
  isLoading: boolean;
  login: (email: string, password: string) => Promise<void>;
  register: (email: string, password: string) => Promise<void>;
  logout: () => void;
  refreshToken: () => Promise<void>;
}

Security Considerations

  • Passwords hashed with bcrypt (cost factor 12)
  • JWT tokens signed with HS256 algorithm
  • Refresh tokens hashed before database storage
  • Rate limiting: 5 login attempts per IP per minute
  • CORS configured for frontend origin only
  • HttpOnly cookies for refresh token storage (production)
  • CSRF tokens for state-changing operations

Testing Standards

[Source: docs/architecture.md#testing]

  • Unit Tests: backend/tests/unit/test_auth_service.py

    • Test JWT generation and validation
    • Test password hashing and verification
    • Test email token generation
    • Mock external dependencies (database, email)
  • Integration Tests: backend/tests/integration/test_auth_api.py

    • Test complete registration flow
    • Test login with valid/invalid credentials
    • Test token refresh mechanism
    • Test password reset flow
    • Use test database with rollback
  • Frontend Tests: frontend/src/components/auth/__tests__/

    • Test form validation
    • Test error handling
    • Test auth context behavior
    • Mock API responses

Change Log

Date Version Description Author
2025-08-26 1.0 Initial story creation Claude (Scrum Master)

Dev Agent Record

Agent Model Used

To be populated during implementation

Debug Log References

To be populated during implementation

Completion Notes List

To be populated during implementation

File List

Backend Files Created/Modified:

  • backend/models/user.py - User, RefreshToken, APIKey, EmailVerificationToken, PasswordResetToken models
  • backend/models/api_models.py - BaseResponse, ErrorResponse, SuccessResponse classes
  • backend/services/auth_service.py - Authentication logic, JWT handling, password management
  • backend/services/email_service.py - Email sending, templates, verification
  • backend/services/ai_service.py - Added ModelUsage dataclass
  • backend/api/auth.py - Authentication endpoints
  • backend/core/config.py - AuthSettings configuration
  • backend/core/security.py - Password hashing, JWT utilities
  • backend/core/dependencies.py - get_current_user, require_user dependencies
  • backend/core/exceptions.py - Authentication exceptions, YouTubeError
  • backend/models/video.py - Added VideoSummary model
  • backend/main.py - Added auth router
  • backend/.env.example - Environment variables documentation
  • backend/tests/unit/test_auth_service.py - Unit tests for auth service
  • backend/tests/integration/test_auth_api.py - Integration tests for auth endpoints

Frontend Files Created:

  • frontend/src/contexts/AuthContext.tsx - Authentication context and state management
  • frontend/src/components/auth/LoginForm.tsx - Login form with validation
  • frontend/src/components/auth/RegisterForm.tsx - Registration with password strength
  • frontend/src/components/auth/ForgotPasswordForm.tsx - Password reset request
  • frontend/src/components/auth/ResetPasswordForm.tsx - Password reset confirmation
  • frontend/src/components/auth/EmailVerification.tsx - Email verification handler
  • frontend/src/components/auth/ProtectedRoute.tsx - Route protection wrapper
  • frontend/src/components/auth/UserMenu.tsx - User dropdown menu
  • frontend/src/components/auth/index.ts - Barrel export for auth components
  • frontend/src/components/ui/dropdown-menu.tsx - Radix dropdown component
  • frontend/src/components/ui/avatar.tsx - Radix avatar component
  • frontend/src/pages/auth/LoginPage.tsx - Login page layout
  • frontend/src/pages/auth/RegisterPage.tsx - Registration page layout
  • frontend/src/pages/auth/ForgotPasswordPage.tsx - Forgot password page
  • frontend/src/pages/auth/ResetPasswordPage.tsx - Reset password page
  • frontend/src/pages/auth/EmailVerificationPage.tsx - Email verification page
  • frontend/src/pages/auth/index.ts - Barrel export for auth pages
  • frontend/src/services/apiClient.ts - Updated with auth instance export
  • frontend/src/App.tsx - Updated with authentication routing

Database Migrations:

  • alembic/versions/xxxx_add_authentication_tables.py - Users and auth tables migration

QA Results

To be populated after QA review