Files
WealthWise/backend/app/core/security.py

112 lines
2.9 KiB
Python
Raw Normal View History

"""Security utilities for authentication and password management.
This module provides:
- Password hashing and verification using bcrypt
- JWT token creation and validation
- Security-related helper functions
"""
import bcrypt
from datetime import datetime, timedelta, timezone
from typing import Any, Optional
from jose import jwt
from app.core.config import get_settings
settings = get_settings()
def verify_password(plain_password: str, hashed_password: str) -> bool:
"""Verify a plain password against a hashed password.
Args:
plain_password: The plain text password to verify
hashed_password: The bcrypt hashed password from database
Returns:
True if password matches, False otherwise
"""
return bcrypt.checkpw(
plain_password.encode('utf-8'),
hashed_password.encode('utf-8')
)
def get_password_hash(password: str) -> str:
"""Generate a bcrypt hash from a plain password.
Args:
password: The plain text password to hash
Returns:
Bcrypt hashed password string
"""
return bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt()).decode('utf-8')
def create_access_token(
data: dict[str, Any],
expires_delta: Optional[timedelta] = None,
) -> str:
"""Create a JWT access token.
This function creates a JWT token with the provided data payload.
The token includes an expiration time and is signed with the
application's secret key.
Args:
data: Dictionary of claims to encode in the token (e.g., {"sub": user_id})
expires_delta: Optional custom expiration time. Defaults to settings.ACCESS_TOKEN_EXPIRE_MINUTES
Returns:
Encoded JWT string
Example:
>>> token = create_access_token({"sub": str(user.id)})
>>> # Use token in Authorization: Bearer <token> header
"""
to_encode = data.copy()
# Calculate expiration time
if expires_delta:
expire = datetime.now(timezone.utc) + expires_delta
else:
expire = datetime.now(timezone.utc) + timedelta(
minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES
)
# Add expiration and issued at claims
to_encode.update({
"exp": expire,
"iat": datetime.now(timezone.utc),
"type": "access",
})
# Encode the JWT
encoded_jwt = jwt.encode(
to_encode,
settings.SECRET_KEY,
algorithm=settings.ALGORITHM,
)
return encoded_jwt
def decode_access_token(token: str) -> dict[str, Any]:
"""Decode and validate a JWT access token.
Args:
token: The JWT string to decode
Returns:
Dictionary containing the token payload
Raises:
jwt.JWTError: If token is invalid or expired
"""
return jwt.decode(
token,
settings.SECRET_KEY,
algorithms=[settings.ALGORITHM],
)