Todo-Web / src /services /auth.py
Claude Code - Backend Implementation Specialist
Update dependencies and improve password hashing security
19d86c5
Raw History Blame Contribute Delete
3.28 kB
"""
Authentication service for password hashing and JWT token management.
This module provides utilities for:
- Password hashing and verification using bcrypt
- JWT token creation and decoding
- User authentication workflows
"""
import os
from datetime import datetime, timedelta
from typing import Optional, Dict, Any
from passlib.context import CryptContext
from jose import JWTError, jwt
# Password hashing configuration using Argon2 (more secure and no compatibility issues)
pwd_context = CryptContext(schemes=["argon2"], deprecated="auto")
# JWT configuration from environment variables
JWT_SECRET_KEY = os.getenv("JWT_SECRET_KEY", "your-secret-key-change-in-production")
JWT_ALGORITHM = os.getenv("JWT_ALGORITHM", "HS256")
JWT_EXPIRATION_MINUTES = int(os.getenv("JWT_EXPIRATION_MINUTES", "10080")) # Default: 7 days
def hash_password(password: str) -> str:
"""
Hash a plain text password using Argon2.
Args:
password: Plain text password to hash
Returns:
Hashed password string
Example:
>>> hashed = hash_password("mypassword123")
>>> print(hashed)
$argon2id$...
"""
return pwd_context.hash(password)
def verify_password(plain_password: str, hashed_password: str) -> bool:
"""
Verify a plain text password against a hashed password.
Args:
plain_password: Plain text password to verify
hashed_password: Hashed password to compare against
Returns:
True if password matches, False otherwise
Example:
>>> hashed = hash_password("mypassword123")
>>> verify_password("mypassword123", hashed)
True
>>> verify_password("wrongpassword", hashed)
False
"""
return pwd_context.verify(plain_password, hashed_password)
def create_access_token(data: Dict[str, Any], expires_delta: Optional[timedelta] = None) -> str:
"""
Create a JWT access token with user data.
Args:
data: Dictionary containing user data to encode in token (must include 'user_id')
expires_delta: Optional custom expiration time delta
Returns:
Encoded JWT token string
Example:
>>> token = create_access_token({"user_id": 1, "email": "user@example.com"})
>>> print(token)
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
"""
to_encode = data.copy()
# Set expiration time
if expires_delta:
expire = datetime.utcnow() + expires_delta
else:
expire = datetime.utcnow() + timedelta(minutes=JWT_EXPIRATION_MINUTES)
to_encode.update({"exp": expire})
# Create JWT token
encoded_jwt = jwt.encode(to_encode, JWT_SECRET_KEY, algorithm=JWT_ALGORITHM)
return encoded_jwt
def decode_token(token: str) -> Optional[Dict[str, Any]]:
"""
Decode and verify a JWT token.
Args:
token: JWT token string to decode
Returns:
Dictionary containing decoded token payload, or None if invalid
Example:
>>> token = create_access_token({"user_id": 1})
>>> payload = decode_token(token)
>>> print(payload["user_id"])
1
"""
try:
payload = jwt.decode(token, JWT_SECRET_KEY, algorithms=[JWT_ALGORITHM])
return payload
except JWTError:
return None