Record auth failure by reason.
(&self, reason: &str)
| 117 | |
| 118 | /// Record auth failure by reason. |
| 119 | pub fn record_auth_failure(&self, reason: &str) { |
| 120 | match reason { |
| 121 | "password" => self.auth_failure_password.fetch_add(1, Ordering::Relaxed), |
| 122 | "api_key" => self.auth_failure_api_key.fetch_add(1, Ordering::Relaxed), |
| 123 | "jwt" => self.auth_failure_jwt.fetch_add(1, Ordering::Relaxed), |
| 124 | "expired" => self.auth_failure_expired.fetch_add(1, Ordering::Relaxed), |
| 125 | "blacklisted" => self |
| 126 | .auth_failure_blacklisted |
| 127 | .fetch_add(1, Ordering::Relaxed), |
| 128 | _ => 0, |
| 129 | }; |
| 130 | |
| 131 | // Anomaly: count in current 1-minute window. |
| 132 | self.rotate_window_if_needed(); |
| 133 | self.failed_login_window.fetch_add(1, Ordering::Relaxed); |
| 134 | } |
| 135 | |
| 136 | /// Check if failed login rate exceeds threshold (anomaly alert). |
| 137 | pub fn failed_login_spike(&self, threshold: u64) -> bool { |