You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

47 lines
1.3 KiB
Go

package handler
import (
"crypto/subtle"
"fmt"
"net/http"
)
// BasicAuthConfig configures HTTP Basic authentication middleware.
type BasicAuthConfig struct {
Username string
Password string
Realm string
}
// BasicAuthMiddleware protects routes with HTTP Basic authentication.
// If credentials are not configured, all requests are denied.
func BasicAuthMiddleware(cfg BasicAuthConfig) func(http.Handler) http.Handler {
realm := cfg.Realm
if realm == "" {
realm = "Restricted"
}
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
username, password, ok := r.BasicAuth()
if !ok || !basicAuthCredentialsMatch(username, password, cfg.Username, cfg.Password) {
w.Header().Set("WWW-Authenticate", fmt.Sprintf(`Basic realm="%s", charset="UTF-8"`, realm))
writeJSON(w, http.StatusUnauthorized, map[string]string{
"error": "unauthorized",
})
return
}
next.ServeHTTP(w, r)
})
}
}
func basicAuthCredentialsMatch(gotUser, gotPass, wantUser, wantPass string) bool {
if wantUser == "" || wantPass == "" {
return false
}
userOK := subtle.ConstantTimeCompare([]byte(gotUser), []byte(wantUser)) == 1
passOK := subtle.ConstantTimeCompare([]byte(gotPass), []byte(wantPass)) == 1
return userOK && passOK
}