package authz import ( "context" "encoding/base64" "fmt" "log" "net/http" "github.com/casbin/casbin/v2" "golang.org/x/crypto/bcrypt" ) // Authentication middleware to enforce authentication of all requests. func Authentication(authMap TokenMap, next http.Handler) http.Handler { return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { u, p, ok := req.BasicAuth() if !ok { rw.Header().Set("WWW-Authenticate", `Basic realm="git"`) http.Error(rw, "Authentication Required", 401) return } urn := fmt.Sprintf("uid:%s", u) hash, ok := authMap[urn] if !ok { http.Error(rw, "Bad Request", 400) return } token, err := base64.URLEncoding.DecodeString(p) if err != nil { http.Error(rw, "Bad Request", 400) return } if err := bcrypt.CompareHashAndPassword([]byte(hash), token); err != nil { http.Error(rw, "Bad Request", 400) return } ctx := context.WithValue(req.Context(), "urn", urn) next.ServeHTTP(rw, req.WithContext(ctx)) }) } // Authorization middleware to enforce authoirzation of all requests. func Authorization(enf *casbin.Enforcer, next http.Handler) http.Handler { return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { ctx := req.Context() urn := ctx.Value("urn") repo := req.URL.Path action := req.Method ok, err := enf.Enforce(urn, repo, action) if err != nil { log.Printf("error running enforce %s", err) http.Error(rw, "Bad Request", http.StatusBadRequest) } if !ok { log.Printf("Access denied") http.Error(rw, "Access denied", http.StatusUnauthorized) } log.Printf("Method %s Url %s", action, repo) next.ServeHTTP(rw, req.WithContext(ctx)) }) }