Full-stack Amazon AI Transcreation Platform with: - FastAPI backend (async, PostgreSQL, Redis, Celery) with 11 DB tables - JWT auth (SSO-ready abstract provider pattern) - 6-agent pipeline orchestrator with deterministic modules - Next.js 14 frontend with Amazon branding (Ember fonts, orange/dark theme) - Job wizard, monitoring HUD, output review, admin screens - 154 TM/reference files imported, 12 locales configured - Docker Compose for all services Agents 2-5 (TM retrieval, ranker, transcreator, compliance) are stubs pending Phase 3 LLM integration. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
52 lines
2.2 KiB
Python
52 lines
2.2 KiB
Python
from datetime import datetime, timedelta, timezone
|
|
from typing import Any
|
|
|
|
import bcrypt
|
|
from jose import JWTError, jwt
|
|
|
|
from app.config import settings
|
|
from app.auth.providers.base import AbstractAuthProvider
|
|
|
|
|
|
class JWTAuthProvider(AbstractAuthProvider):
|
|
"""JWT-based authentication provider with bcrypt password hashing."""
|
|
|
|
def __init__(self) -> None:
|
|
self.secret_key = settings.JWT_SECRET_KEY
|
|
self.algorithm = settings.JWT_ALGORITHM
|
|
self.access_token_expiry = timedelta(hours=settings.JWT_EXPIRY_HOURS)
|
|
self.refresh_token_expiry = timedelta(days=7)
|
|
|
|
async def authenticate(self, email: str, password: str) -> dict[str, Any] | None:
|
|
"""Not used directly - authentication happens through AuthService."""
|
|
return None
|
|
|
|
def create_access_token(self, data: dict[str, Any]) -> str:
|
|
"""Create a JWT access token (8-hour expiry by default)."""
|
|
to_encode = data.copy()
|
|
expire = datetime.now(timezone.utc) + self.access_token_expiry
|
|
to_encode.update({"exp": expire, "type": "access"})
|
|
return jwt.encode(to_encode, self.secret_key, algorithm=self.algorithm)
|
|
|
|
def create_refresh_token(self, data: dict[str, Any]) -> str:
|
|
"""Create a JWT refresh token (7-day expiry)."""
|
|
to_encode = data.copy()
|
|
expire = datetime.now(timezone.utc) + self.refresh_token_expiry
|
|
to_encode.update({"exp": expire, "type": "refresh"})
|
|
return jwt.encode(to_encode, self.secret_key, algorithm=self.algorithm)
|
|
|
|
def validate_token(self, token: str) -> dict[str, Any] | None:
|
|
"""Validate a JWT and return its claims, or None if invalid."""
|
|
try:
|
|
payload = jwt.decode(token, self.secret_key, algorithms=[self.algorithm])
|
|
return payload
|
|
except JWTError:
|
|
return None
|
|
|
|
def hash_password(self, password: str) -> str:
|
|
"""Hash a password using bcrypt."""
|
|
return bcrypt.hashpw(password.encode("utf-8"), bcrypt.gensalt()).decode("utf-8")
|
|
|
|
def verify_password(self, plain_password: str, hashed_password: str) -> bool:
|
|
"""Verify a password against a bcrypt hash."""
|
|
return bcrypt.checkpw(plain_password.encode("utf-8"), hashed_password.encode("utf-8"))
|