Rate limit account authentication attempts

This commit is contained in:
Hamza Ayed
2026-10-03 00:59:47 +03:00
parent f745bed0f7
commit 5430d4ac4b
6 changed files with 165 additions and 4 deletions
+26 -3
View File
@@ -1179,7 +1179,16 @@ def create_local_session(request: Request) -> dict[str, Any]:
@app.post("/v1/auth/register", status_code=201)
def register_account(credentials: PasswordCredentials) -> dict[str, Any]:
def register_account(credentials: PasswordCredentials, request: Request) -> dict[str, Any]:
client_host = request.client.host if request.client is not None else "unknown"
retry_after = auth.registration_retry_after(client_host)
if retry_after:
raise HTTPException(
status_code=429,
detail="تم بلوغ حد إنشاء الحسابات من هذا الاتصال؛ حاول لاحقًا.",
headers={"Retry-After": str(retry_after)},
)
auth.record_registration_attempt(client_host)
try:
user_id = auth.create_account(credentials.email, credentials.password)
email = auth.normalize_email(credentials.email)
@@ -1190,13 +1199,27 @@ def register_account(credentials: PasswordCredentials) -> dict[str, Any]:
@app.post("/v1/auth/login")
def login_account(credentials: PasswordCredentials) -> dict[str, Any]:
def login_account(credentials: PasswordCredentials, request: Request) -> dict[str, Any]:
try:
account = auth.authenticate(credentials.email, credentials.password)
email = auth.normalize_email(credentials.email)
except ValueError as exc:
raise HTTPException(status_code=422, detail=str(exc)) from exc
client_host = request.client.host if request.client is not None else "unknown"
retry_after = auth.login_retry_after(email, client_host)
if retry_after:
raise HTTPException(
status_code=429,
detail="محاولات الدخول كثيرة؛ انتظر انتهاء المهلة ثم أعد المحاولة.",
headers={"Retry-After": str(retry_after)},
)
try:
account = auth.authenticate(email, credentials.password)
except ValueError as exc:
raise HTTPException(status_code=422, detail=str(exc)) from exc
if account is None:
auth.record_login_failure(email, client_host)
raise HTTPException(status_code=401, detail="البريد الإلكتروني أو كلمة المرور غير صحيحة.")
auth.clear_login_failures(email, client_host)
user_id, email = account
return _auth_response(user_id, email, "account")