← full-stack-fastapi-template / backend/app/core/security.py
| 1 | from datetime import datetime, timedelta, timezone |
| 2 | from typing import Any |
| 3 | |
| 4 | import jwt |
| 5 | from pwdlib import PasswordHash |
| 6 | from pwdlib.hashers.argon2 import Argon2Hasher |
| 7 | from pwdlib.hashers.bcrypt import BcryptHasher |
| 8 | |
| 9 | from app.core.config import settings |
| 10 | |
| 11 | password_hash = PasswordHash( |
| 12 | ( |
| 13 | Argon2Hasher(), |
| 14 | BcryptHasher(), |
| 15 | ) |
| 16 | ) |
| 17 | |
| 18 | |
| 19 | ALGORITHM = "HS256" |
| 20 | |
| 21 | |
| 22 | def create_access_token(subject: str | Any, expires_delta: timedelta) -> str: |
| 23 | expire = datetime.now(timezone.utc) + expires_delta |
| 24 | to_encode = {"exp": expire, "sub": str(subject)} |
| 25 | encoded_jwt = jwt.encode(to_encode, settings.SECRET_KEY, algorithm=ALGORITHM) |
| 26 | return encoded_jwt |
| 27 | |
| 28 | |
| 29 | def verify_password( |
| 30 | plain_password: str, hashed_password: str |
| 31 | ) -> tuple[bool, str | None]: |
| 32 | return password_hash.verify_and_update(plain_password, hashed_password) |
| 33 | |
| 34 | |
| 35 | def get_password_hash(password: str) -> str: |
| 36 | return password_hash.hash(password) |
| 37 |