Tahasaif3 commited on
Commit
b58515e
·
verified ·
1 Parent(s): e9ec39d

Update src/utils/security.py

Browse files
Files changed (1) hide show
  1. src/utils/security.py +64 -22
src/utils/security.py CHANGED
@@ -2,56 +2,98 @@ from passlib.context import CryptContext
2
  from datetime import datetime, timedelta
3
  from typing import Optional, Union
4
  import uuid
 
5
  from jose import JWTError, jwt
6
  from ..config import settings
7
 
 
 
 
 
 
 
 
 
 
8
  # Password hashing context
9
  pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
10
 
11
 
12
  def hash_password(password: str) -> str:
13
  """Hash a password using bcrypt."""
14
- return pwd_context.hash(password)
 
 
 
 
15
 
16
 
17
  def verify_password(plain_password: str, hashed_password: str) -> bool:
18
  """Verify a plain password against its hash."""
19
- return pwd_context.verify(plain_password, hashed_password)
 
 
 
 
20
 
21
 
22
  def create_access_token(data: dict, expires_delta: Optional[timedelta] = None) -> str:
23
  """Create a JWT access token."""
24
- to_encode = data.copy()
 
25
 
26
- if expires_delta:
27
- expire = datetime.utcnow() + expires_delta
28
- else:
29
- # Default to 7 days if no expiration is provided
30
- expire = datetime.utcnow() + timedelta(days=settings.ACCESS_TOKEN_EXPIRE_DAYS)
31
 
32
- to_encode.update({"exp": expire, "iat": datetime.utcnow()})
 
 
 
 
 
 
33
 
34
- encoded_jwt = jwt.encode(to_encode, settings.JWT_SECRET_KEY, algorithm=settings.JWT_ALGORITHM)
35
- return encoded_jwt
 
 
 
36
 
37
 
38
  def verify_token(token: str) -> Optional[dict]:
39
  """Verify a JWT token and return the payload if valid."""
40
  try:
41
- payload = jwt.decode(token, settings.JWT_SECRET_KEY, algorithms=[settings.JWT_ALGORITHM])
 
 
 
 
 
42
  return payload
43
- except JWTError:
 
 
 
 
44
  return None
45
 
46
 
47
  def verify_user_id_from_token(token: str) -> Optional[uuid.UUID]:
48
  """Extract user_id from JWT token."""
49
- payload = verify_token(token)
50
- if payload:
51
- user_id_str = payload.get("sub")
52
- if user_id_str:
53
- try:
54
- return uuid.UUID(user_id_str)
55
- except ValueError:
56
- return None
57
- return None
 
 
 
 
 
 
2
  from datetime import datetime, timedelta
3
  from typing import Optional, Union
4
  import uuid
5
+ import logging
6
  from jose import JWTError, jwt
7
  from ..config import settings
8
 
9
+ # Configure logger
10
+ logger = logging.getLogger(__name__)
11
+ logger.setLevel(logging.DEBUG)
12
+
13
+ # Fallback values for JWT settings
14
+ _FALLBACK_JWT_SECRET_KEY = "fallback_secret_key_for_development_only"
15
+ _FALLBACK_JWT_ALGORITHM = "HS256"
16
+ _FALLBACK_ACCESS_TOKEN_EXPIRE_DAYS = 7
17
+
18
  # Password hashing context
19
  pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
20
 
21
 
22
  def hash_password(password: str) -> str:
23
  """Hash a password using bcrypt."""
24
+ try:
25
+ return pwd_context.hash(password)
26
+ except Exception as e:
27
+ logger.error(f"Error hashing password: {str(e)}")
28
+ raise
29
 
30
 
31
  def verify_password(plain_password: str, hashed_password: str) -> bool:
32
  """Verify a plain password against its hash."""
33
+ try:
34
+ return pwd_context.verify(plain_password, hashed_password)
35
+ except Exception as e:
36
+ logger.error(f"Error verifying password: {str(e)}")
37
+ return False
38
 
39
 
40
  def create_access_token(data: dict, expires_delta: Optional[timedelta] = None) -> str:
41
  """Create a JWT access token."""
42
+ try:
43
+ to_encode = data.copy()
44
 
45
+ if expires_delta:
46
+ expire = datetime.utcnow() + expires_delta
47
+ else:
48
+ # Default to 7 days if no expiration is provided
49
+ expire = datetime.utcnow() + timedelta(days=getattr(settings, 'ACCESS_TOKEN_EXPIRE_DAYS', _FALLBACK_ACCESS_TOKEN_EXPIRE_DAYS))
50
 
51
+ to_encode.update({"exp": expire, "iat": datetime.utcnow()})
52
+
53
+ # Use fallback values if settings are not properly configured
54
+ secret_key = getattr(settings, 'JWT_SECRET_KEY', _FALLBACK_JWT_SECRET_KEY)
55
+ algorithm = getattr(settings, 'JWT_ALGORITHM', _FALLBACK_JWT_ALGORITHM)
56
+
57
+ logger.debug(f"Creating token with settings: SECRET_KEY={secret_key}, ALGORITHM={algorithm}")
58
 
59
+ encoded_jwt = jwt.encode(to_encode, secret_key, algorithm=algorithm)
60
+ return encoded_jwt
61
+ except Exception as e:
62
+ logger.error(f"Error creating access token: {str(e)}")
63
+ raise
64
 
65
 
66
  def verify_token(token: str) -> Optional[dict]:
67
  """Verify a JWT token and return the payload if valid."""
68
  try:
69
+ # Use fallback values if settings are not properly configured
70
+ secret_key = getattr(settings, 'JWT_SECRET_KEY', _FALLBACK_JWT_SECRET_KEY)
71
+ algorithm = getattr(settings, 'JWT_ALGORITHM', _FALLBACK_JWT_ALGORITHM)
72
+
73
+ logger.debug(f"Verifying token with settings: SECRET_KEY={secret_key}, ALGORITHM={algorithm}")
74
+ payload = jwt.decode(token, secret_key, algorithms=[algorithm])
75
  return payload
76
+ except JWTError as e:
77
+ logger.warning(f"JWT Error during token verification: {str(e)}")
78
+ return None
79
+ except Exception as e:
80
+ logger.error(f"Unexpected error during token verification: {str(e)}")
81
  return None
82
 
83
 
84
  def verify_user_id_from_token(token: str) -> Optional[uuid.UUID]:
85
  """Extract user_id from JWT token."""
86
+ try:
87
+ payload = verify_token(token)
88
+ if payload:
89
+ user_id_str = payload.get("sub")
90
+ if user_id_str:
91
+ try:
92
+ return uuid.UUID(user_id_str)
93
+ except ValueError as e:
94
+ logger.warning(f"Invalid UUID format in token payload: {user_id_str} - {str(e)}")
95
+ return None
96
+ return None
97
+ except Exception as e:
98
+ logger.error(f"Error extracting user ID from token: {str(e)}")
99
+ return None