AuthRateLimiter

struct AuthRateLimiter

Limits brute-force guessing against login, password change, password recovery, username lookup, and account creation.

Each guessable thing (a client IP, a username, a registration code) gets a bucket in AuthRateLimitStore. Handlers call reserve before checking credentials, which counts the attempt up front so that concurrent requests can’t race past the limit, then call Reservation.refund once the credentials check out. So in effect only failures count. Going over a bucket’s limit locks it for 15 minutes, doubling with each further lockout within a day, up to 24 hours. Locked callers get a 429 with a Retry-After header.

Buckets are keyed on the submitted username or code, not on whether it exists, so a lockout doesn’t reveal which accounts exist.

Settings.authRateLimitEnabled turns all of this off; each limit in Settings can also be set to 0 to disable just that limit.

  • A counter for one thing an attacker might guess against, with its own limit and counting window.

    See more

    Declaration

    Swift

    struct Bucket
  • Attempts counted by reserve. Call refund once the attempt succeeds.

    See more

    Declaration

    Swift

    struct Reservation
  • Declaration

    Swift

    static let baseLockout: Int
  • Declaration

    Swift

    static let maxLockout: Int
  • reserve(_:on:) Asynchronous

    Counts an attempt against each bucket, in order. Throws a 429 if any bucket is locked or goes over its limit; buckets after that one aren’t touched. List the client IP bucket first, so that a locked-out IP can’t run up the counts on accounts.

    Declaration

    Swift

    static func reserve(_ buckets: [Bucket], on req: Request) async throws -> Reservation
  • clearAllLockouts(on:) Asynchronous

    Clears every current lockout, for every kind of bucket. Returns the number of lockouts cleared.

    Declaration

    Swift

    static func clearAllLockouts(on req: Request) async -> Int
  • clear(_:on:) Asynchronous

    Clears the counts and lockouts for these buckets. Used when staff unlock an account.

    Declaration

    Swift

    static func clear(_ buckets: [Bucket], on req: Request) async