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
- Email/password registration with verification email
- Secure password requirements enforced (minimum 8 characters, complexity rules)
- JWT-based authentication with refresh tokens
- Password reset functionality via email
- Optional OAuth integration with Google for single sign-on
- 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 modelsbackend/models/api_models.py- BaseResponse, ErrorResponse, SuccessResponse classesbackend/services/auth_service.py- Authentication logic, JWT handling, password managementbackend/services/email_service.py- Email sending, templates, verificationbackend/services/ai_service.py- Added ModelUsage dataclassbackend/api/auth.py- Authentication endpointsbackend/core/config.py- AuthSettings configurationbackend/core/security.py- Password hashing, JWT utilitiesbackend/core/dependencies.py- get_current_user, require_user dependenciesbackend/core/exceptions.py- Authentication exceptions, YouTubeErrorbackend/models/video.py- Added VideoSummary modelbackend/main.py- Added auth routerbackend/.env.example- Environment variables documentationbackend/tests/unit/test_auth_service.py- Unit tests for auth servicebackend/tests/integration/test_auth_api.py- Integration tests for auth endpoints
Frontend Files Created:
frontend/src/contexts/AuthContext.tsx- Authentication context and state managementfrontend/src/components/auth/LoginForm.tsx- Login form with validationfrontend/src/components/auth/RegisterForm.tsx- Registration with password strengthfrontend/src/components/auth/ForgotPasswordForm.tsx- Password reset requestfrontend/src/components/auth/ResetPasswordForm.tsx- Password reset confirmationfrontend/src/components/auth/EmailVerification.tsx- Email verification handlerfrontend/src/components/auth/ProtectedRoute.tsx- Route protection wrapperfrontend/src/components/auth/UserMenu.tsx- User dropdown menufrontend/src/components/auth/index.ts- Barrel export for auth componentsfrontend/src/components/ui/dropdown-menu.tsx- Radix dropdown componentfrontend/src/components/ui/avatar.tsx- Radix avatar componentfrontend/src/pages/auth/LoginPage.tsx- Login page layoutfrontend/src/pages/auth/RegisterPage.tsx- Registration page layoutfrontend/src/pages/auth/ForgotPasswordPage.tsx- Forgot password pagefrontend/src/pages/auth/ResetPasswordPage.tsx- Reset password pagefrontend/src/pages/auth/EmailVerificationPage.tsx- Email verification pagefrontend/src/pages/auth/index.ts- Barrel export for auth pagesfrontend/src/services/apiClient.ts- Updated with auth instance exportfrontend/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