package auth import ( "context" "net/http" "github.com/sirupsen/logrus" ) // Middleware get User from session and put it in context type Middleware struct { authorizer *Authorizer log *logrus.Entry } type authContextKey string // NewMiddleware returns a new authentication middleware func NewMiddleware(authorizer *Authorizer, log *logrus.Entry) *Middleware { return &Middleware{ authorizer: authorizer, log: log.WithField("middleware", "auth"), } } func (m *Middleware) ServeHTTP(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) { user, err := m.authorizer.CurrentUser(w, r) if err != nil { http.Error(w, err.Error(), http.StatusUnauthorized) return } if user != nil { m.log.Debugf("setting user %s in the context", user.GetName()) } else { m.log.Debugf("got a nil user in the context") } ctxKey := authContextKey("auth.user") ctx := context.WithValue(r.Context(), ctxKey, user) r = r.WithContext(ctx) next(w, r) } // MiddlewareRole handles the role checking for the current user type MiddlewareRole struct { authorizer *Authorizer log *logrus.Entry role string } // NewMiddlewareRole returns a new MiddlewareRole func NewMiddlewareRole(authorizer *Authorizer, log *logrus.Entry, role string) *MiddlewareRole { return &MiddlewareRole{ authorizer: authorizer, log: log.WithField("middleware", "role"), role: role, } } func (m *MiddlewareRole) ServeHTTP(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) { user := GetCurrentUser(r, m.log) if user == nil || !user.HasRole(m.role) { if user == nil { m.log.Debug("user is nil in the context") } else { m.log.Debug("user doesn't have the role") } // return unauthorized http.Error(w, "Invalid user role", http.StatusUnauthorized) return } if !user.IsActivated() { // return unauthorized http.Error(w, "User is not activated", http.StatusUnauthorized) return } m.log.Debug("user has the role and is activated, continuing") next(w, r) } // GetCurrentUser gets the current user from the request context func GetCurrentUser(r *http.Request, log *logrus.Entry) User { log.Debug("getting user from context") ctxKey := authContextKey("auth.user") u := r.Context().Value(ctxKey) if u == nil { return nil } user, ok := u.(User) if !ok { panic("invalid user type") } return user }