portainer/api/middleware.go

66 lines
1.7 KiB
Go

package main
import (
"fmt"
"github.com/dgrijalva/jwt-go"
"net/http"
"strings"
)
func addMiddleware(h http.Handler, middleware ...func(http.Handler) http.Handler) http.Handler {
for _, mw := range middleware {
h = mw(h)
}
return h
}
// authenticate provides Authentication middleware for handlers
func (api *api) authenticate(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var token string
// Get token from the Authorization header
// format: Authorization: Bearer
tokens, ok := r.Header["Authorization"]
if ok && len(tokens) >= 1 {
token = tokens[0]
token = strings.TrimPrefix(token, "Bearer ")
}
if token == "" {
http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
return
}
parsedToken, err := jwt.Parse(token, func(token *jwt.Token) (interface{}, error) {
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
msg := fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
return nil, msg
}
return api.secret, nil
})
if err != nil {
http.Error(w, "Invalid JWT token", http.StatusUnauthorized)
return
}
if parsedToken == nil || !parsedToken.Valid {
http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
return
}
// context.Set(r, "user", parsedToken)
next.ServeHTTP(w, r)
return
})
}
// SecureHeaders adds secure headers to the API
func secureHeaders(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Add("X-Content-Type-Options", "nosniff")
w.Header().Add("X-Frame-Options", "DENY")
next.ServeHTTP(w, r)
})
}