func (con Login) Handler(c context.Context) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { l := webfw.GetLogger(c) sess := webfw.GetSession(c, r) renderData := renderer.RenderData{} if r.Method == "GET" { if v, ok := sess.Flash("form-error"); ok { renderData["form-error"] = v } } else { if err := r.ParseForm(); err != nil { l.Fatal(err) } username := data.Login(r.Form.Get("username")) password := r.Form.Get("password") repo := GetRepo(c) conf := GetConfig(c) u := repo.UserByLogin(username) formError := false if u.Err() != nil { sess.SetFlash("form-error", "login-incorrect") formError = true } else if !u.Authenticate(password, []byte(conf.Auth.Secret)) { sess.SetFlash("form-error", "login-incorrect") formError = true } else { sess.Set(AuthUserKey, u) sess.Set(AuthNameKey, username) } if formError { http.Redirect(w, r, r.URL.String(), http.StatusTemporaryRedirect) } else { var returnPath string if v, ok := sess.Flash("return-to"); ok { returnPath = v.(string) } else { returnPath = webfw.GetDispatcher(c).Pattern } http.Redirect(w, r, returnPath, http.StatusTemporaryRedirect) } return } err := webfw.GetRenderCtx(c, r)(w, renderData, "login.tmpl") if err != nil { l.Print(err) } } }
func (con Login) Handler(c context.Context) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { l := webfw.GetLogger(c) sess := webfw.GetSession(c, r) data := renderer.RenderData{} if r.Method == "GET" { if v, ok := sess.Flash("form-error"); ok { data["form-error"] = v } } else { if err := r.ParseForm(); err != nil { l.Fatal(err) } username := r.Form.Get("username") password := r.Form.Get("password") db := GetDB(c) formError := false if u, err := db.GetUser(username); err != nil { sess.SetFlash("form-error", "login-incorrect") formError = true } else if !u.Authenticate(password) { sess.SetFlash("form-error", "login-incorrect") formError = true } else { sess.Set(authkey, u) sess.Set(namekey, u.Login) } if formError { http.Redirect(w, r, r.URL.String(), http.StatusTemporaryRedirect) } else { var returnPath string if v, ok := sess.Flash("return-to"); ok { returnPath = v.(string) } else { returnPath = webfw.GetDispatcher(c).Pattern } http.Redirect(w, r, returnPath, http.StatusTemporaryRedirect) } return } err := webfw.GetRenderCtx(c, r)(w, data, "login.tmpl") if err != nil { l.Print(err) } } }
func (mw Auth) Handler(ph http.Handler, c context.Context, l *log.Logger) http.Handler { handler := func(w http.ResponseWriter, r *http.Request) { for _, prefix := range mw.IgnoreURLPrefix { if prefix[0] == '/' { prefix = prefix[1:] } if strings.HasPrefix(r.URL.Path, mw.Pattern+prefix+"/") { ph.ServeHTTP(w, r) return } } route, _, ok := webfw.GetDispatcher(c).RequestRoute(r) if !ok { ph.ServeHTTP(w, r) return } switch ac := route.Controller.(type) { case AuthController: if !ac.LoginRequired(c, r) { ph.ServeHTTP(w, r) return } sess := webfw.GetSession(c, r) var u User validUser := false if uv, ok := sess.Get(authkey); ok { if u, ok = uv.(User); ok { validUser = true } } if !validUser { if uv, ok := sess.Get(namekey); ok { if n, ok := uv.(string); ok { var err error u, err = mw.DB.GetUser(n) if err == nil { validUser = true sess.Set(authkey, u) } else if _, ok := err.(ValidationError); !ok { l.Print(err) } } } } if validUser && !u.Active { Debug.Println("User " + u.Login + " is inactive") validUser = false } if !validUser { d := webfw.GetDispatcher(c) sess.SetFlash(CtxKey("return-to"), r.URL.Path) path := d.NameToPath("auth-login", webfw.MethodGet) if path == "" { path = "/" } http.Redirect(w, r, path, http.StatusMovedPermanently) return } case ApiAuthController: if !ac.AuthRequired(c, r) { ph.ServeHTTP(w, r) return } var u User var err error auth := r.Header.Get("Authorization") validUser := false if auth != "" { switch { default: if !strings.HasPrefix(auth, "Readeef ") { break } auth = auth[len("Readeef "):] parts := strings.SplitN(auth, ":", 2) login := parts[0] u, err = mw.DB.GetUser(login) if err != nil { l.Printf("Error getting db user '%s': %v\n", login, err) break } var decoded []byte decoded, err = base64.StdEncoding.DecodeString(parts[1]) if err != nil { l.Printf("Error decoding auth header: %v\n", err) break } date := r.Header.Get("X-Date") t, err := time.Parse(http.TimeFormat, date) if err != nil || t.Add(30*time.Second).Before(time.Now()) { break } nonce := r.Header.Get("X-Nonce") if !mw.Nonce.Check(nonce) { break } mw.Nonce.Remove(nonce) buf := util.BufferPool.GetBuffer() defer util.BufferPool.Put(buf) buf.ReadFrom(r.Body) r.Body = ioutil.NopCloser(buf) bodyHash := md5.New() if _, err := bodyHash.Write(buf.Bytes()); err != nil { l.Printf("Error generating the hash for the request body: %v\n", err) break } contentMD5 := base64.StdEncoding.EncodeToString(bodyHash.Sum(nil)) message := fmt.Sprintf("%s\n%s\n%s\n%s\n%s\n%s\n", r.RequestURI, r.Method, contentMD5, r.Header.Get("Content-Type"), date, nonce) b := make([]byte, base64.StdEncoding.EncodedLen(len(u.MD5API))) base64.StdEncoding.Encode(b, u.MD5API) hm := hmac.New(sha256.New, b) if _, err := hm.Write([]byte(message)); err != nil { l.Printf("Error generating the hashed message: %v\n", err) break } if !hmac.Equal(hm.Sum(nil), decoded) { l.Printf("Error matching the supplied auth message to the generated one.\n") break } if !u.Active { Debug.Println("User " + u.Login + " is inactive") break } validUser = true } } if !validUser { w.WriteHeader(http.StatusForbidden) return } c.Set(r, context.BaseCtxKey("user"), u) } ph.ServeHTTP(w, r) } return http.HandlerFunc(handler) }
func (mw Auth) Handler(ph http.Handler, c context.Context) http.Handler { logger := webfw.GetLogger(c) handler := func(w http.ResponseWriter, r *http.Request) { for _, prefix := range mw.IgnoreURLPrefix { if prefix[0] == '/' { prefix = prefix[1:] } if strings.HasPrefix(r.URL.Path, mw.Pattern+prefix+"/") { ph.ServeHTTP(w, r) return } } route, _, ok := webfw.GetDispatcher(c).RequestRoute(r) if !ok { ph.ServeHTTP(w, r) return } repo := GetRepo(c) switch ac := route.Controller.(type) { case AuthController: if !ac.LoginRequired(c, r) { ph.ServeHTTP(w, r) return } sess := webfw.GetSession(c, r) var u content.User validUser := false if uv, ok := sess.Get(AuthUserKey); ok { if u, ok = uv.(content.User); ok { validUser = true } } if !validUser { if uv, ok := sess.Get(AuthNameKey); ok { if n, ok := uv.(data.Login); ok { u = repo.UserByLogin(n) if u.HasErr() { logger.Print(u.Err()) } else { validUser = true sess.Set(AuthUserKey, u) } } } } if validUser && !u.Data().Active { logger.Infoln("User " + u.Data().Login + " is inactive") validUser = false } if !validUser { d := webfw.GetDispatcher(c) sess.SetFlash(CtxKey("return-to"), r.URL.Path) path := d.NameToPath("auth-login", webfw.MethodGet) if path == "" { path = "/" } http.Redirect(w, r, path, http.StatusMovedPermanently) return } case ApiAuthController: if !ac.AuthRequired(c, r) { ph.ServeHTTP(w, r) return } url, login, signature, nonce, date, t := authData(r) validUser := false var u content.User if login != "" && signature != "" && !t.IsZero() { switch { default: u = repo.UserByLogin(data.Login(login)) if u.HasErr() { logger.Printf("Error getting db user '%s': %v\n", login, u.Err()) break } decoded, err := base64.StdEncoding.DecodeString(signature) if err != nil { logger.Printf("Error decoding auth header: %v\n", err) break } if t.Add(30 * time.Second).Before(time.Now()) { break } if !mw.Nonce.Check(nonce) { break } mw.Nonce.Remove(nonce) buf := util.BufferPool.GetBuffer() defer util.BufferPool.Put(buf) buf.ReadFrom(r.Body) r.Body = ioutil.NopCloser(buf) bodyHash := md5.New() if _, err := bodyHash.Write(buf.Bytes()); err != nil { logger.Printf("Error generating the hash for the request body: %v\n", err) break } contentMD5 := base64.StdEncoding.EncodeToString(bodyHash.Sum(nil)) message := fmt.Sprintf("%s\n%s\n%s\n%s\n%s\n%s\n", url, r.Method, contentMD5, r.Header.Get("Content-Type"), date, nonce) b := make([]byte, base64.StdEncoding.EncodedLen(len(u.Data().MD5API))) base64.StdEncoding.Encode(b, u.Data().MD5API) hm := hmac.New(sha256.New, b) if _, err := hm.Write([]byte(message)); err != nil { logger.Printf("Error generating the hashed message: %v\n", err) break } if !hmac.Equal(hm.Sum(nil), decoded) { logger.Printf("Error matching the supplied auth message to the generated one.\n") break } if !u.Data().Active { logger.Println("User " + u.Data().Login + " is inactive") break } validUser = true } } if validUser { c.Set(r, context.BaseCtxKey("user"), u) } else { if rej, ok := ac.(AuthRejectHandler); ok { rej.AuthReject(c, r) } else { w.WriteHeader(http.StatusUnauthorized) return } } } ph.ServeHTTP(w, r) } return http.HandlerFunc(handler) }