feat(auth): add password length validation

- introduce password_too_long function to check bcrypt's 72-byte limit
- update registration and login to handle passwords exceeding limit
This commit is contained in:
nocci 2025-12-06 13:20:06 +00:00
parent 8f17f9bf8d
commit 1b673f2cdf
2 changed files with 25 additions and 0 deletions

View file

@ -7,6 +7,7 @@ from sqlmodel import Session, select
from .db import get_session from .db import get_session
from .models import User from .models import User
BCRYPT_MAX_BYTES = 72
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
@ -20,6 +21,14 @@ def verify_password(plain_password: str, hashed_password: str) -> bool:
return pwd_context.verify(plain_password, hashed_password) return pwd_context.verify(plain_password, hashed_password)
def password_too_long(password: str) -> bool:
"""Return True if password exceeds bcrypt's 72-byte limit."""
try:
return len(password.encode("utf-8")) > BCRYPT_MAX_BYTES
except Exception:
return True
def get_current_user( def get_current_user(
request: Request, request: Request,
session: Session = Depends(get_session), session: Session = Depends(get_session),

View file

@ -21,6 +21,7 @@ from .utils import (
from .auth import ( from .auth import (
hash_password, hash_password,
verify_password, verify_password,
password_too_long,
get_current_user, get_current_user,
require_current_user, require_current_user,
require_admin, require_admin,
@ -142,6 +143,8 @@ def register(
error = None error = None
if password != password_confirm: if password != password_confirm:
error = "Passwords do not match." error = "Passwords do not match."
elif password_too_long(password):
error = "Passwort ist zu lang (max. 72 Bytes). Bitte kürzer wählen."
else: else:
existing = session.exec( existing = session.exec(
select(User).where(User.username == username) select(User).where(User.username == username)
@ -221,6 +224,19 @@ def login(
status_code=400, status_code=400,
) )
if password_too_long(password):
token = ensure_csrf_token(request)
return templates.TemplateResponse(
"login.html",
{
"request": request,
"error": "Passwort ist zu lang (max. 72 Bytes).",
"current_user": None,
"csrf_token": token,
},
status_code=400,
)
user = session.exec(select(User).where(User.username == username)).first() user = session.exec(select(User).where(User.username == username)).first()
error = None error = None
if not user or not verify_password(password, user.password_hash): if not user or not verify_password(password, user.password_hash):