05/02/2026 updated code for security 6
This commit is contained in:
@@ -191,6 +191,7 @@ def login():
|
||||
|
||||
|
||||
@auth_bp.route('/logout', methods=['POST'])
|
||||
@limiter.limit('60 per minute')
|
||||
def logout():
|
||||
"""Blacklist both the access token (from header) and refresh token (from body)."""
|
||||
auth_header = request.headers.get('Authorization', '')
|
||||
@@ -230,6 +231,7 @@ def refresh():
|
||||
# ── MFA / TOTP endpoints ─────────────────────────────────────────────────────
|
||||
|
||||
@auth_bp.route('/mfa/setup', methods=['GET'])
|
||||
@limiter.limit('10 per minute')
|
||||
@require_jwt
|
||||
def mfa_setup():
|
||||
"""Generate a new TOTP secret and return QR code (as base64 PNG data URI)."""
|
||||
@@ -261,6 +263,7 @@ def mfa_setup():
|
||||
|
||||
|
||||
@auth_bp.route('/mfa/enable', methods=['POST'])
|
||||
@limiter.limit('10 per minute')
|
||||
@require_jwt
|
||||
def mfa_enable():
|
||||
"""Enable MFA after verifying the first TOTP code. Returns one-time backup codes."""
|
||||
@@ -306,6 +309,7 @@ def mfa_enable():
|
||||
|
||||
|
||||
@auth_bp.route('/mfa/disable', methods=['POST'])
|
||||
@limiter.limit('10 per minute')
|
||||
@require_jwt
|
||||
def mfa_disable():
|
||||
"""Disable MFA after verifying the current TOTP code or a backup code."""
|
||||
@@ -420,6 +424,7 @@ def mfa_verify():
|
||||
|
||||
|
||||
@auth_bp.route('/mfa/status', methods=['GET'])
|
||||
@limiter.limit('60 per minute')
|
||||
@require_jwt
|
||||
def mfa_status():
|
||||
user = db.session.get(User, g.current_user_id)
|
||||
@@ -432,6 +437,7 @@ def mfa_status():
|
||||
|
||||
|
||||
@auth_bp.route('/mfa/backup-codes/regenerate', methods=['POST'])
|
||||
@limiter.limit('5 per minute')
|
||||
@require_jwt
|
||||
def mfa_backup_codes_regenerate():
|
||||
"""
|
||||
@@ -474,6 +480,7 @@ def mfa_backup_codes_regenerate():
|
||||
|
||||
|
||||
@auth_bp.route('/me', methods=['GET'])
|
||||
@limiter.limit('60 per minute')
|
||||
@require_jwt
|
||||
def me():
|
||||
"""Return basic profile info for the authenticated user."""
|
||||
@@ -532,6 +539,7 @@ def audit_log():
|
||||
# ── Account management ────────────────────────────────────────────────────────
|
||||
|
||||
@auth_bp.route('/change-password', methods=['POST'])
|
||||
@limiter.limit('5 per minute')
|
||||
@require_jwt
|
||||
def change_password():
|
||||
"""
|
||||
@@ -622,6 +630,7 @@ def change_password():
|
||||
|
||||
|
||||
@auth_bp.route('/account', methods=['DELETE'])
|
||||
@limiter.limit('3 per minute')
|
||||
@require_jwt
|
||||
def delete_account():
|
||||
"""
|
||||
@@ -673,6 +682,7 @@ def delete_account():
|
||||
# ── Account Recovery ──────────────────────────────────────────────────────────
|
||||
|
||||
@auth_bp.route('/recovery/setup', methods=['POST'])
|
||||
@limiter.limit('10 per minute')
|
||||
@require_jwt
|
||||
def recovery_setup():
|
||||
"""
|
||||
@@ -710,6 +720,7 @@ def recovery_setup():
|
||||
|
||||
|
||||
@auth_bp.route('/recovery/status', methods=['GET'])
|
||||
@limiter.limit('60 per minute')
|
||||
@require_jwt
|
||||
def recovery_status():
|
||||
"""Return whether the user has a recovery code configured."""
|
||||
|
||||
Reference in New Issue
Block a user