|
36 | 36 | logger = logging.getLogger(__name__) |
37 | 37 | security_logger = get_security_logger() |
38 | 38 |
|
| 39 | +# HTTPException detail strings that indicate security-critical rejections |
| 40 | +# (revoked tokens, disabled accounts, fail-secure validation errors). |
| 41 | +# Only these trigger a hard JSON deny in the auth middleware; all other |
| 42 | +# 401/403s fall through to route-level auth for backwards compatibility. |
| 43 | +_HARD_DENY_DETAILS = frozenset({"Token has been revoked", "Account disabled", "Token validation failed"}) |
| 44 | + |
39 | 45 |
|
40 | 46 | def _should_log_auth_success() -> bool: |
41 | 47 | """Check if successful authentication should be logged based on settings. |
@@ -146,12 +152,6 @@ async def dispatch(self, request: Request, call_next: Callable) -> Response: |
146 | 152 | logger.debug(f"Failed to close database session: {close_error}") |
147 | 153 |
|
148 | 154 | except HTTPException as e: |
149 | | - # Only hard-deny for security-critical rejections (revoked tokens, |
150 | | - # disabled accounts). Other 401s (e.g. malformed tokens, missing |
151 | | - # claims) fall through so route-level auth can handle them — this |
152 | | - # preserves backwards compatibility with registration scripts and |
153 | | - # other callers that use minimal JWT claims. |
154 | | - _HARD_DENY_DETAILS = frozenset({"Token has been revoked", "Account disabled", "Token validation failed"}) |
155 | 155 | if e.status_code in (401, 403) and e.detail in _HARD_DENY_DETAILS: |
156 | 156 | logger.info(f"✗ Auth rejected ({e.status_code}): {e.detail}") |
157 | 157 |
|
|
0 commit comments