github.com/richardwilkes/toolbox@v1.121.0/xio/network/xhttp/basic_auth.go (about) 1 // Copyright (c) 2016-2024 by Richard A. Wilkes. All rights reserved. 2 // 3 // This Source Code Form is subject to the terms of the Mozilla Public 4 // License, version 2.0. If a copy of the MPL was not distributed with 5 // this file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 // 7 // This Source Code Form is "Incompatible With Secondary Licenses", as 8 // defined by the Mozilla Public License, version 2.0. 9 10 // Package xhttp provides HTTP-related utilities. 11 package xhttp 12 13 import ( 14 "crypto/subtle" 15 "fmt" 16 "net/http" 17 ) 18 19 // BasicAuth provides basic HTTP authentication. 20 type BasicAuth struct { 21 // Lookup provides a way to map a user in a realm to a password. The returned password should have already been 22 // passed through the Hasher function. 23 Lookup func(user, realm string) ([]byte, bool) 24 Hasher func(input string) []byte 25 Realm string 26 } 27 28 // Wrap an http.Handler, requiring Basic Authentication. 29 func (ba *BasicAuth) Wrap(handler http.Handler) http.Handler { 30 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 31 if user, pw, ok := r.BasicAuth(); ok { 32 stored, found := ba.Lookup(user, ba.Realm) 33 passwordMatch := subtle.ConstantTimeCompare(ba.Hasher(pw), stored) == 1 34 if found && passwordMatch { 35 if md := MetadataFromRequest(r); md != nil { 36 md.User = user 37 md.Logger = md.Logger.With("user", user) 38 } 39 handler.ServeHTTP(w, r) 40 return 41 } 42 } 43 w.Header().Set("WWW-Authenticate", fmt.Sprintf(`Basic realm=%q, charset="UTF-8"`, ba.Realm)) 44 ErrorStatus(w, http.StatusUnauthorized) 45 }) 46 }