first commit - MVE Incrementables Parser microservice with FastAPI, JWT, Celery, Redis
This commit is contained in:
61
app/api/auth.py
Normal file
61
app/api/auth.py
Normal file
@@ -0,0 +1,61 @@
|
||||
"""Authentication endpoints."""
|
||||
from fastapi import APIRouter, HTTPException, status, Request
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
|
||||
from app.core.config import get_settings
|
||||
from app.core.security import authenticate_user, create_access_token, check_rate_limit
|
||||
from app.schemas import LoginRequest, LoginResponse
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
router = APIRouter(prefix="/auth", tags=["Authentication"])
|
||||
|
||||
|
||||
@router.post("/login", response_model=LoginResponse)
|
||||
async def login(request: Request, credentials: LoginRequest):
|
||||
"""
|
||||
Authenticate user and return JWT token.
|
||||
|
||||
- **username**: Username
|
||||
- **password**: Password
|
||||
|
||||
Returns JWT access token with expiration time.
|
||||
"""
|
||||
settings = get_settings()
|
||||
|
||||
# Get client IP for rate limiting
|
||||
client_ip = request.client.host if request.client else "unknown"
|
||||
|
||||
# Check rate limit
|
||||
if check_rate_limit(client_ip):
|
||||
logger.warning(f"Rate limit exceeded for IP: {client_ip}")
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_429_TOO_MANY_REQUESTS,
|
||||
detail="Too many login attempts. Please try again later."
|
||||
)
|
||||
|
||||
# Authenticate (never log the password)
|
||||
logger.info(f"Login attempt for user: {credentials.username} from IP: {client_ip}")
|
||||
|
||||
if not authenticate_user(credentials.username, credentials.password):
|
||||
logger.warning(f"Failed login attempt for user: {credentials.username}")
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Invalid credentials",
|
||||
headers={"WWW-Authenticate": "Bearer"},
|
||||
)
|
||||
|
||||
# Create access token
|
||||
access_token_expires = timedelta(minutes=settings.jwt_expires_minutes)
|
||||
access_token = create_access_token(
|
||||
data={"sub": credentials.username},
|
||||
expires_delta=access_token_expires
|
||||
)
|
||||
|
||||
logger.info(f"Successful login for user: {credentials.username}")
|
||||
|
||||
return LoginResponse(
|
||||
access_token=access_token,
|
||||
token_type="bearer",
|
||||
expires_in=settings.jwt_expires_minutes * 60 # Convert to seconds
|
||||
)
|
||||
Reference in New Issue
Block a user