func (o *rerouteOutputter) Output(code int, g *gas.Gas) { var cookieVal string if o.data != nil { buf := new(bytes.Buffer) enc := gob.NewEncoder(buf) err := enc.Encode(o.data) // TODO: do we want to ignore an encode error here? if err != nil { Error(g, err).Output(code, g) return } cookieVal = base64.StdEncoding.EncodeToString(buf.Bytes()) } g.SetCookie(&http.Cookie{ Path: "/", Name: "_reroute", Value: cookieVal, Expires: time.Now().Add(60 * time.Second), HttpOnly: true, }) redirectOutputter(o.path).Output(code, g) }
// SignIn signs the user in by creating a new session and setting a cookie on // the client. func SignIn(g *gas.Gas, u User, password string) error { if store == nil { return ErrNoStore } // already signed in? sess, _ := GetSession(g) if sess != nil { cookie, err := g.Cookie("s") if err != nil && err != http.ErrNoCookie { return err } if err = VerifyCookie(cookie); err != nil { return err } id, err := base64.StdEncoding.DecodeString(cookie.Value) if err != nil { return err } //id := []byte(cookie.Value) if err := store.Update(id); err != nil { return err } return nil } pass, salt, err := u.Secrets() if err != nil { return err } if !VerifyHash([]byte(password), pass, salt) { return ErrBadPassword } username := u.Username() sessid := make([]byte, Env.SessidLen) rand.Read(sessid) err = store.Create(sessid, time.Now().Add(Env.MaxCookieAge), username) if err != nil { return err } cookie := &http.Cookie{ Name: "s", Path: "/", Value: base64.StdEncoding.EncodeToString(sessid), MaxAge: int(Env.MaxCookieAge / time.Second), HttpOnly: true, } SignCookie(cookie) g.SetCookie(cookie) return nil }
// SignOut signs the user out, destroying the associated session and cookie. func SignOut(g *gas.Gas) error { if store == nil { return ErrNoStore } cookie, err := g.Cookie("s") if err != nil { return err } if err := VerifyCookie(cookie); err != nil { return err } id, err := base64.StdEncoding.DecodeString(cookie.Value) if err != nil { return err } //id := []byte(cookie.Value) if err := store.Delete(id); err != nil && err != sql.ErrNoRows { return err } cookie = &http.Cookie{ Name: "s", Path: "/", Value: "", Expires: time.Time{}, MaxAge: -1, HttpOnly: true, } SignCookie(cookie) g.SetCookie(cookie) return nil }
// CheckReroute is a middleware handler that will check for and deal with // reroute cookies func CheckReroute(g *gas.Gas) (int, gas.Outputter) { reroute, err := g.Cookie("_reroute") if reroute != nil { if err == nil { blob, err := base64.StdEncoding.DecodeString(reroute.Value) if err == nil { g.SetData("_reroute", blob) } else { log.Println("gas: dispatch reroute:", err) } } else { log.Println("gas: reroute cookie:", err) } // Empty the cookie out and toss it back reroute.Value = "" reroute.MaxAge = -1 g.SetCookie(reroute) } return g.Continue() }