BasicAuth
Basic Authentication middleware for Fiber that provides HTTP basic auth. It calls the next handler for valid credentials and returns 401 Unauthorized for missing or invalid credentials, 400 Bad Request for malformed Authorization headers, among them a request that carries the field on more than one line, or 431 Request Header Fields Too Large when the header exceeds size limits. Credentials may omit Base64 padding as permitted by RFC 7235's token68 syntax.
The default unauthorized response includes the header WWW-Authenticate: Basic realm="Restricted", charset="UTF-8", sets Cache-Control: no-store, and adds Authorization to the Vary header, keeping the fields an earlier middleware put there. Only the UTF-8 charset is supported; any other value will panic. Generated realm and charset values are escaped as RFC 9110 HTTP quoted strings.
With no Users and no Authorizer, which is what New() called without a config gives, no credentials are valid and no request is let through: well-formed credentials, or none, are answered 401 Unauthorized, and a malformed Authorization header still gets 400 Bad Request.
Signaturesβ
func New(config ...Config) fiber.Handler
func UsernameFromContext(ctx any) string
UsernameFromContext accepts a fiber.CustomCtx, fiber.Ctx, a *fasthttp.RequestCtx, or a context.Context.
Examplesβ
Import the middleware package:
import (
"github.com/gofiber/fiber/v3"
"github.com/gofiber/fiber/v3/middleware/basicauth"
)
Once your Fiber app is initialized, choose one of the following approaches:
// Provide a minimal config
app.Use(basicauth.New(basicauth.Config{
Users: map[string]string{
// "doe" hashed using SHA-256
"john": "{SHA256}eZ75KhGvkY4/t0HfQpNPO1aO0tk6wd908bjUGieTKm8=",
// "123456" hashed using bcrypt
"admin": "$2a$10$gTYwCN66/tBRoCr3.TXa1.v1iyvwIF7GRBqxzv7G.AHLMt/owXrp.",
},
}))
// Or extend your config for customization
app.Use(basicauth.New(basicauth.Config{
Users: map[string]string{
// "doe" hashed using SHA-256
"john": "{SHA256}eZ75KhGvkY4/t0HfQpNPO1aO0tk6wd908bjUGieTKm8=",
// "123456" hashed using bcrypt
"admin": "$2a$10$gTYwCN66/tBRoCr3.TXa1.v1iyvwIF7GRBqxzv7G.AHLMt/owXrp.",
},
Realm: "Forbidden",
Unauthorized: func(c fiber.Ctx) error {
return c.SendFile("./unauthorized.html")
},
}))
// Or check the credentials yourself. Users is not consulted when Authorizer is set,
// so Authorizer has to verify the password as well.
app.Use(basicauth.New(basicauth.Config{
Authorizer: func(user, pass string, c fiber.Ctx) bool {
// custom validation logic, for example a lookup of a stored hash
return checkCredentials(user, pass)
},
}))
Password hashesβ
Passwords must be supplied in pre-hashed form. The middleware detects the hashing algorithm from a prefix:
"{SHA512}"or"{SHA256}"followed by a base64-encoded digest- standard bcrypt strings beginning with
$2
If no prefix is present, the value is interpreted as a SHA-256 digest encoded in hex or base64. Plaintext passwords are rejected.
The middleware decodes the credentials as UTF-8 and normalizes them to Unicode
NFC before it compares them, so hash a password that contains non-ASCII
characters in its NFC form. Credentials that are not valid UTF-8, or that
contain control characters, are answered with 400 Bad Request.
The decoded digest must be exactly the size of the named algorithm β 32 bytes
for SHA-256, 64 bytes for SHA-512. A digest of any other length could never
match a password, so it is rejected at startup: New() panics with
ErrInvalidSHA256PasswordLength or ErrInvalidSHA512PasswordLength rather than
starting with an account that can never authenticate. The most common cause is
a truncated copy/paste, or a SHA-256 digest stored under the {SHA512} prefix.
Every attempt runs one check per configured hash tier, meaning each algorithm
and each bcrypt cost in Users, whether the user exists or not, so response
time reveals neither. A setup with a single tier pays for one check. A mixed
one, for example while migrating from SHA-256 to bcrypt or to a higher bcrypt
cost, pays for one check per tier on every attempt.
Generating SHA-256 and SHA-512 passwordsβ
Create a digest, encode it in base64, and prefix it with {SHA256} or
{SHA512} before adding it to Users:
# SHA-256
printf 'secret' | openssl dgst -binary -sha256 | base64
# SHA-512
printf 'secret' | openssl dgst -binary -sha512 | base64
Include the prefix in your config:
Users: map[string]string{
"john": "{SHA256}K7gNU3sdo+OL0wNhqoVWhr3g6s1xYv72ol/pe/Unols=",
"admin": "{SHA512}vSsar3708Jvp9Szi2NWZZ02Bqp1qRCFpbcTZPdBhnWgs5WtNZKnvCXdhztmeD2cmW192CF5bDufKRpayrW/isg==",
}
Configβ
| Property | Type | Description | Default |
|---|---|---|---|
| Next | func(fiber.Ctx) bool | Next defines a function to skip this middleware when it returns true. | nil |
| Users | map[string]string | Users maps usernames to hashed passwords (e.g. bcrypt, {SHA256}). | map[string]string{} |
| Realm | string | Realm is a string to define the realm attribute of BasicAuth. The realm identifies the system to authenticate against and can be used by clients to save credentials. | "Restricted" |
| Charset | string | Charset sent in the WWW-Authenticate header. Only "UTF-8" is supported (case-insensitive). | "UTF-8" |
| HeaderLimit | int | Maximum allowed length of the Authorization header. Requests exceeding this limit are rejected. | 8192 |
| Authorizer | func(string, string, fiber.Ctx) bool | Authorizer defines a function to check the credentials. It will be called with a username, password, and the current context and is expected to return true or false to indicate approval. When set, it replaces the check against Users, which is then neither consulted nor validated. | nil |
| Unauthorized | fiber.Handler | Unauthorized defines the response body for unauthorized responses. | nil |
| BadRequest | fiber.Handler | BadRequest defines the response for malformed Authorization headers, a request carrying the field on more than one line included. | nil |
Default Configβ
var ConfigDefault = Config{
Next: nil,
Users: map[string]string{},
Realm: "Restricted",
Charset: "UTF-8",
HeaderLimit: 8192,
Authorizer: nil,
Unauthorized: nil,
BadRequest: nil,
}