Configuration: HTTP basic authentication

This page documents the basic_auth directive for HTTP Basic Authentication that requests use for access control. Ferron supports only hashed passwords. For security reasons, plaintext passwords cause a configuration validation error.

Global directives⁠#

basic_auth_concurrency⁠#

{
    basic_auth_concurrency 64
}

This is a global-only directive that limits the number of concurrent password verification tasks across all basic_auth blocks. Password hashing is computationally expensive, and this limit prevents a flood of authentication requests from exhausting server resources.

Value typeDescriptionDefault
<positive integer>Maximum concurrent password verification tasks.128
falseDisable the limit (unlimited concurrency).disabled

Configuration example: reduce concurrency

{
    basic_auth_concurrency 32
}

Configuration example: disable the limit

{
    basic_auth_concurrency false
}

Configuration example: set minimum of 1

{
    basic_auth_concurrency 1
}
Note
  • Ferron treats values less than 1 as 1.
  • Setting this too low may cause authentication requests to queue under load, increasing latency.
  • Set this to false only if you understand the resource implications, since that removes the limit.
  • When Ferron reaches the limit, further authentication requests wait for a free slot instead of failing.

basic_auth⁠#

example.com {
    basic_auth {
        realm "Restricted Area"
        users {
            alice "$argon2id$v=19$m=19456,t=2,p=1$..."
            bob "$argon2id$v=19$m=19456,t=2,p=1$..."
        }

        brute_force_protection {
            max_attempts 5
            lockout_duration "15m"
            window "5m"
        }
    }
}

You can define multiple basic_auth blocks. Ferron merges the users from all blocks.

Nested directiveArgumentsDescriptionDefault
realm<string>Authentication realm shown in the browser auth dialog.Restricted Access
usersblockUser credentials block (username to hash mappings). Required.none
brute_force_protectionblock or falseBrute-force attack protection settings. Set to false to disable the protection.enabled (see below)

users block⁠#

Each entry inside the users block maps a username to a hashed password:

users {
    alice "$argon2id$v=19$m=19456,t=2,p=1$..."
    bob "$argon2id$v=19$m=19456,t=2,p=1$..."
}

Ferron accepts only hashed passwords. Ferron supports the following hash formats:

PrefixAlgorithm
$argon2id$Argon2id (recommended)
$argon2i$Argon2i
$argon2d$Argon2d
$pbkdf2$PBKDF2 (HMAC-SHA1)
$pbkdf2-sha256$PBKDF2-SHA256
$pbkdf2-sha384$PBKDF2-SHA384
$pbkdf2-sha512$PBKDF2-SHA512
$scrypt$scrypt
Note
  • Use the ferron-passwd utility, which ships with Ferron, to create password hashes.
  • Ferron shows the realm value in the browser authentication dialog.
  • Configuration validation fails if any password value is not a recognized hash format.
  • Base64 salt and hash fields accept both padded and unpadded encodings.
  • PBKDF2 hashes accept a bare iteration count ($pbkdf2-sha256$600000$...) or the PHC parameter form ($pbkdf2-sha256$i=600000,l=32$...).

brute_force_protection block⁠#

Brute-force protection is enabled by default to protect against credential-guessing attacks.

Nested directiveTypeDefaultDescription
max_attempts<int>5Maximum failed attempts before lockout.
lockout_duration<duration>15mHow long to lock the account after exceeding max attempts.
window<duration>5mSliding window for counting attempts.

Duration strings accept suffixes: 30s, 15m, 1h, 1d. Ferron treats plain numbers without a suffix as seconds.

Forward proxy (CONNECT) support⁠#

When authentication fails for a CONNECT request, the stage returns a 407 Proxy Authentication Required response instead of 401.

Brute-force protection behavior⁠#

When brute-force protection is active:

  • The stage records each failed authentication attempt per-IP with a timestamp.
  • If max_attempts failures occur within the window duration, Ferron locks the IP.
  • During lockout, the stage rejects all authentication attempts for that IP immediately.
  • After lockout_duration, the lockout expires and the stage resets the attempt history.

Examples⁠#

Basic authentication with Argon2 hashes⁠#

admin.example.com {
    basic_auth {
        realm "Admin Panel"
        users {
            admin "$argon2id$v=19$m=19456,t=2,p=1$c2FsdHNhbHQ$..."
        }
    }

    root /var/www/admin
}

Forward proxy with authentication⁠#

proxy.example.com {
    basic_auth {
        realm "Proxy Access"
        users {
            user1 "$argon2id$v=19$m=19456,t=2,p=1$..."
            user2 "$argon2id$v=19$m=19456,t=2,p=1$..."
        }

        brute_force_protection {
            max_attempts 3
            lockout_duration "30m"
            window "10m"
        }
    }

    forward_proxy {
        allow_domains "example.com" "*.example.com"
        allow_ports 80 443
    }
}

Disabling brute-force protection⁠#

example.com {
    basic_auth {
        realm "Behind WAF"
        users {
            deploy "$argon2id$v=19$m=19456,t=2,p=1$..."
        }

        brute_force_protection false
    }
}
Warning

Disabling brute-force protection exposes your users to credential-guessing attacks. Only do this if you have equivalent protection at another layer.

Security considerations⁠#

  • Always use TLS. Basic Auth credentials travel in the Authorization header. Ferron base64-encodes them but does not encrypt them. Without TLS, an attacker can intercept the credentials in transit.
  • Use Argon2id. This is the recommended algorithm for password hashing. It resists GPU-based attacks and side-channel attacks.
  • Use strong passwords. The security of the hash depends on the entropy of the original password.
  • Ferron rejects plaintext passwords. It does not accept plaintext passwords at all.
  • Brute-force protection runs by default. This gives a reasonable baseline of protection without requiring additional configuration.
  • Tune basic_auth_concurrency to your workload. Setting it too low may cause authentication queuing under high load. Setting it too high may allow a flood of expensive hash operations to exhaust resources.

Observability⁠#

Access log fields⁠#

The basic authentication module contributes the following field to the HTTP access log line:

FieldTypeDescription
ferron.basicauth.resultstringAuth outcome: skip, failure, or success.

Trace spans⁠#

The basic authentication stage sets the following attributes on its ferron.stage.basicauth span:

AttributeTypeDescription
ferron.basicauth.resultstringAuthentication result: success, failure, or skip.
user.namestringThe authenticated username, on success.
error.typestringSet to auth_failed on authentication failure, enabling trace UI highlighting.

Best practices⁠#

ferron doctor reports the following best-practice checks for directives on this page.

  • basic_auth_concurrency false: Disabling the global password-verification concurrency limit removes backpressure on expensive hash checks. Keep a bounded limit.
  • Non-Argon2id password hashes: Prefer Argon2id for new Basic Auth credentials. Other hash algorithms are weaker against offline attacks.
  • brute_force_protection { enabled false }: Disabling credential-guessing protection removes a layer of security. Only disable when equivalent protection exists at another layer.