github.com/shoshinnikita/budget-manager@v0.7.1-0.20220131195411-8c46ff1c6778/internal/web/middlewares/auth.go (about)

     1  package middlewares
     2  
     3  import (
     4  	"net/http"
     5  
     6  	"golang.org/x/crypto/bcrypt"
     7  
     8  	"github.com/ShoshinNikita/budget-manager/internal/logger"
     9  	"github.com/ShoshinNikita/budget-manager/internal/pkg/errors"
    10  	"github.com/ShoshinNikita/budget-manager/internal/pkg/reqid"
    11  	"github.com/ShoshinNikita/budget-manager/internal/web/utils"
    12  )
    13  
    14  type Credentials interface {
    15  	Get(username string) (secret string, ok bool)
    16  }
    17  
    18  func BasicAuthMiddleware(h http.Handler, creds Credentials, log logger.Logger) http.Handler {
    19  	errUnauthorized := errors.New("unauthorized")
    20  
    21  	checkAuth := func(r *http.Request) bool {
    22  		username, password, ok := r.BasicAuth()
    23  		if !ok {
    24  			return false
    25  		}
    26  		hashedPassword, ok := creds.Get(username)
    27  		if !ok {
    28  			return false
    29  		}
    30  
    31  		return bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(password)) == nil
    32  	}
    33  
    34  	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    35  		ctx := r.Context()
    36  		log := reqid.FromContextToLogger(ctx, log)
    37  		log = log.WithFields(logger.Fields{"ip": r.RemoteAddr})
    38  
    39  		if !checkAuth(r) {
    40  			log.Warn("invalid auth request")
    41  
    42  			w.Header().Set("WWW-Authenticate", `Basic realm="Budget Manager"`)
    43  			utils.EncodeError(ctx, w, log, errUnauthorized, http.StatusUnauthorized)
    44  			return
    45  		}
    46  
    47  		log.Debug("successful auth request")
    48  		h.ServeHTTP(w, r)
    49  	})
    50  }