package utils import ( "fmt" "log" "net/http" "os" "strings" "github.com/dustinpianalto/errors" "github.com/dustinpianalto/quartermaster" "github.com/golang-jwt/jwt" "github.com/gorilla/mux" ) var jwtKey = []byte(os.Getenv("JWT_KEY")) func Mount(r *mux.Router, path string, handler http.Handler) { r.PathPrefix(path).Handler( http.StripPrefix( strings.TrimSuffix(path, "/"), handler, ), ) } type RootHandler func(http.ResponseWriter, *http.Request) error func (rh RootHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { err := rh(w, r) if err == nil { return } log.Println(err) e, ok := err.(*errors.Error) if !ok { w.WriteHeader(http.StatusInternalServerError) return } w.Header().Set("Content-Type", "application/json; charset=utf-8") if errors.Is(errors.Permission, e) { body := getErrorBody("Permission Denied") w.WriteHeader(http.StatusForbidden) w.Write(body) } if errors.Is(errors.Incorrect, e) && strings.Contains(string(e.Method), "login") { body := getErrorBody("Invalid Login Credentials") w.WriteHeader(http.StatusUnauthorized) w.Write(body) } if errors.Is(errors.Incorrect, e) && strings.Contains(string(e.Method), "refresh") { body := getErrorBody("Missing or Invalid Cookie") w.WriteHeader(http.StatusUnauthorized) w.Write(body) } if errors.Is(errors.Malformed, e) { body := getErrorBody("Bad Request") w.WriteHeader(http.StatusBadRequest) w.Write(body) } if errors.Is(errors.Internal, e) { body := getErrorBody("Internal Server Error") w.WriteHeader(http.StatusInternalServerError) w.Write(body) } if errors.Is(errors.Conflict, e) && strings.Contains(string(e.Method), "register") { body := getErrorBody("User already exists") w.WriteHeader(http.StatusConflict) w.Write(body) } } func getErrorBody(s string) []byte { return []byte(fmt.Sprintf("{\"error\": \"%s\"}", s)) } func IsAuthenticated(r *http.Request) (*jwt.Token, error) { const method errors.Method = "utils/IsAuthenticated" c, err := r.Cookie("token") if err != nil { if err == http.ErrNoCookie { return nil, errors.E(method, errors.Incorrect, "cookie not found", err) } return nil, errors.E(method, errors.Malformed, "failed to get cookie data", err) } tknStr := c.Value claims := &quartermaster.Claims{} tkn, err := jwt.ParseWithClaims(tknStr, claims, func(token *jwt.Token) (interface{}, error) { return jwtKey, nil }) if err != nil { if err == jwt.ErrSignatureInvalid { return nil, errors.E(method, errors.Incorrect, "cookie is invalid", err) } e, _ := err.(*jwt.ValidationError) if e.Inner == jwt.ErrInvalidKeyType { return nil, errors.E(method, errors.Internal, err) } else if e.Inner == jwt.ErrHashUnavailable { return nil, errors.E(method, errors.Internal, err) } return nil, errors.E(method, errors.Malformed, "failed to parse cookie", err) } return tkn, nil }