package auth import ( "context" "net/http" ) type contextKey string type Provider interface { // Returns true if pass is a valid password for the given user Valid(user, pass string) bool } // Require wraps hdlr so that it requires authentication to use. Requests handled by hdlr will have the user // name attached to their context. Use the User function to retrieve it. func Require(hdlr http.HandlerFunc, provider Provider) http.HandlerFunc { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { user, pass, ok := r.BasicAuth() if !ok { w.Header().Add("WWW-Authenticate", `Basic realm="In Vino Veritas"`) w.WriteHeader(http.StatusUnauthorized) return } if !provider.Valid(user, pass) { w.Header().Add("WWW-Authenticate", `Basic realm="In Vino Veritas"`) w.WriteHeader(http.StatusUnauthorized) return } key := contextKey("user") ctx := context.WithValue(r.Context(), key, user) hdlr(w, r.WithContext(ctx)) }) } // User returns the user from r's context. If r has no user in its context, the empty string will be returned. func User(r *http.Request) string { val := r.Context().Value(contextKey("user")) if val == nil { return "" } return val.(string) }