func TestRediStore(t *testing.T) { var req *http.Request var rsp *ResponseRecorder var hdr http.Header var err error var ok bool var cookies []string var session *sessions.Session var flashes []interface{} // Copyright 2012 The Gorilla Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Round 1 ---------------------------------------------------------------- // RedisStore store := NewRediStore(10, "tcp", ":6379", "", []byte("secret-key")) defer store.Close() req, _ = http.NewRequest("GET", "http://localhost:8080/", nil) rsp = NewRecorder() // Get a session. if session, err = store.Get(req, "session-key"); err != nil { t.Fatalf("Error getting session: %v", err) } // Get a flash. flashes = session.Flashes() if len(flashes) != 0 { t.Errorf("Expected empty flashes; Got %v", flashes) } // Add some flashes. session.AddFlash("foo") session.AddFlash("bar") // Custom key. session.AddFlash("baz", "custom_key") // Save. if err = sessions.Save(req, rsp); err != nil { t.Fatalf("Error saving session: %v", err) } hdr = rsp.Header() cookies, ok = hdr["Set-Cookie"] if !ok || len(cookies) != 1 { t.Fatalf("No cookies. Header:", hdr) } // Round 2 ---------------------------------------------------------------- req, _ = http.NewRequest("GET", "http://localhost:8080/", nil) req.Header.Add("Cookie", cookies[0]) rsp = NewRecorder() // Get a session. if session, err = store.Get(req, "session-key"); err != nil { t.Fatalf("Error getting session: %v", err) } // Check all saved values. flashes = session.Flashes() if len(flashes) != 2 { t.Fatalf("Expected flashes; Got %v", flashes) } if flashes[0] != "foo" || flashes[1] != "bar" { t.Errorf("Expected foo,bar; Got %v", flashes) } flashes = session.Flashes() if len(flashes) != 0 { t.Errorf("Expected dumped flashes; Got %v", flashes) } // Custom key. flashes = session.Flashes("custom_key") if len(flashes) != 1 { t.Errorf("Expected flashes; Got %v", flashes) } else if flashes[0] != "baz" { t.Errorf("Expected baz; Got %v", flashes) } flashes = session.Flashes("custom_key") if len(flashes) != 0 { t.Errorf("Expected dumped flashes; Got %v", flashes) } // RediStore specific // Set MaxAge to -1 to mark for deletion. session.Options.MaxAge = -1 // Save. if err = sessions.Save(req, rsp); err != nil { t.Fatalf("Error saving session: %v", err) } // Round 3 ---------------------------------------------------------------- // Custom type // RedisStore store = NewRediStore(10, "tcp", ":6379", "", []byte("secret-key")) defer store.Close() req, _ = http.NewRequest("GET", "http://localhost:8080/", nil) rsp = NewRecorder() // Get a session. if session, err = store.Get(req, "session-key"); err != nil { t.Fatalf("Error getting session: %v", err) } // Get a flash. flashes = session.Flashes() if len(flashes) != 0 { t.Errorf("Expected empty flashes; Got %v", flashes) } // Add some flashes. session.AddFlash(&FlashMessage{42, "foo"}) // Save. if err = sessions.Save(req, rsp); err != nil { t.Fatalf("Error saving session: %v", err) } hdr = rsp.Header() cookies, ok = hdr["Set-Cookie"] if !ok || len(cookies) != 1 { t.Fatalf("No cookies. Header:", hdr) } // Round 4 ---------------------------------------------------------------- // Custom type req, _ = http.NewRequest("GET", "http://localhost:8080/", nil) req.Header.Add("Cookie", cookies[0]) rsp = NewRecorder() // Get a session. if session, err = store.Get(req, "session-key"); err != nil { t.Fatalf("Error getting session: %v", err) } // Check all saved values. flashes = session.Flashes() if len(flashes) != 1 { t.Fatalf("Expected flashes; Got %v", flashes) } custom := flashes[0].(FlashMessage) if custom.Type != 42 || custom.Message != "foo" { t.Errorf("Expected %#v, got %#v", FlashMessage{42, "foo"}, custom) } // RediStore specific // Set MaxAge to -1 to mark for deletion. session.Options.MaxAge = -1 // Save. if err = sessions.Save(req, rsp); err != nil { t.Fatalf("Error saving session: %v", err) } // Round 5 ---------------------------------------------------------------- // RediStore Delete session (deprecated) //req, _ = http.NewRequest("GET", "http://localhost:8080/", nil) //req.Header.Add("Cookie", cookies[0]) //rsp = NewRecorder() //// Get a session. //if session, err = store.Get(req, "session-key"); err != nil { // t.Fatalf("Error getting session: %v", err) //} //// Delete session. //if err = store.Delete(req, rsp, session); err != nil { // t.Fatalf("Error deleting session: %v", err) //} //// Get a flash. //flashes = session.Flashes() //if len(flashes) != 0 { // t.Errorf("Expected empty flashes; Got %v", flashes) //} //hdr = rsp.Header() //cookies, ok = hdr["Set-Cookie"] //if !ok || len(cookies) != 1 { // t.Fatalf("No cookies. Header:", hdr) //} // Round 6 ---------------------------------------------------------------- // RediStore change MaxLength of session store = NewRediStore(10, "tcp", ":6379", "", []byte("secret-key")) req, err = http.NewRequest("GET", "http://www.example.com", nil) if err != nil { t.Fatal("failed to create request", err) } w := httptest.NewRecorder() session, err = store.New(req, "my session") session.Values["big"] = make([]byte, base64.StdEncoding.DecodedLen(4096*2)) err = session.Save(req, w) if err == nil { t.Fatal("expected an error, got nil") } store.MaxLength(4096 * 3) // A bit more than the value size to account for encoding overhead. err = session.Save(req, w) if err != nil { t.Fatal("failed to Save:", err) } }
// Clear will remove all the tokens. Call after a permission change. func Clear(w http.ResponseWriter, r *http.Request, sess *sessions.Session) { // Delete the map if it doesn't exist if _, ok := sess.Values[TokenName]; ok { delete(sess.Values, TokenName) sess.Save(r, w) } }
func fakeCookies(req *http.Request, email, userid, token, csrftoken string) error { var err error var session *sessions.Session resp := httptest.NewRecorder() session, err = sessionStore.Get(req, SESSION_NAME) if len(email) > 0 { session.Values[SESSION_EMAIL] = email } if len(userid) > 0 { session.Values[SESSION_USERID] = userid } if len(token) > 0 { session.Values[SESSION_TOKEN] = token } if len(csrftoken) > 0 { session.Values[SESSION_CSRFTOKEN] = csrftoken } if err = session.Save(req, resp); err != nil { return fmt.Errorf("Could not set cookie! %s", err.Error()) } fcookies, ok := resp.HeaderMap["Set-Cookie"] if !ok { return fmt.Errorf("Cookie not set in header") } req.Header.Add("Cookie", strings.Split(fcookies[0], ";")[0]) return nil }
// Token will return a token. If SingleToken = true, it will return the same token for every page. func Token(w http.ResponseWriter, r *http.Request, sess *sessions.Session) string { // Generate the map if it doesn't exist if _, ok := sess.Values[TokenName]; !ok { sess.Values[TokenName] = make(StringMap) } path := r.URL.Path if SingleToken { path = "/" } sessMap := sess.Values[TokenName].(StringMap) if _, ok := sessMap[path]; !ok { if len(sessMap) >= MaxTokens { for i, _ := range sessMap { delete(sessMap, i) } } sessMap[path] = generate(TokenLength) sess.Save(r, w) } return sessMap[path] }
func googleDisconnect(w http.ResponseWriter, r *http.Request, session *sessions.Session) *appError { token := session.Values["accessToken"] if token == nil { m := "Current user not connected" return &appError{errors.New(m), m, 401} } // Execute HTTP GET request to revoke current token url := "https://accounts.google.com/o/oauth2/revoke?token=" + token.(string) resp, err := http.Get(url) if err != nil { m := "Failed to revoke token for a given user" return &appError{errors.New(m), m, 400} } defer resp.Body.Close() // Reset the user's session session.Values["accessToken"] = nil session.Values["userId"] = nil session.Values["gplusID"] = nil session.Save(r, w) return nil }
func createSession(w http.ResponseWriter, r *http.Request, session *sessions.Session) *ServerSession { // Each session needs a unique ID in order to be saved. if session.ID == "" { session.ID = tokens.NewSessionID() } ss := &ServerSession{ CSRFToken: tokens.NewCSRFToken(session.ID), } // Attempt to store the session. Remove the session if it's not stored // correctly. if err := ss.StoreSession(session.ID); err != nil { RemoveSession(session.ID) glog.Fatalln(err) } // Similarly, save it in our FS storage and set the user's cookie. if err := session.Save(r, w); err != nil { RemoveSession(session.ID) glog.Fatalln(err) } return ss }
// ValidateAuth validates that the user cookie is set up before calling the // handler passed as parameter. func ValidateAuth(h httputils.ContextHandler) httputils.ContextHandler { return func(ctx context.Context, w http.ResponseWriter, r *http.Request) error { var ( sessionData *httputils.SessionData err error ok bool cookieStore *sessions.CookieStore session *sessions.Session cfg = ctx.Value("config").(*config.Config) ) cookieStore, ok = ctx.Value("cookieStore").(*sessions.CookieStore) if !ok { httputils.WriteError(w, http.StatusInternalServerError, "") return fmt.Errorf("validate auth: could not cast value as cookie store: %s", ctx.Value("cookieStore")) } session, err = cookieStore.Get(r, cfg.SessionCookieName) if err != nil { log.Println(err) http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized) return nil } sessionData, ok = session.Values["data"].(*httputils.SessionData) if !ok || sessionData.IsInvalid() { http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized) return nil } else if time.Now().After(sessionData.ExpiresAt) { session.Options.MaxAge = -1 session.Save(r, w) http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized) return nil } // Extend the session's lifetime. cfg, ok = ctx.Value("config").(*config.Config) if !ok { httputils.WriteError(w, http.StatusInternalServerError, "") return fmt.Errorf("validate auth: error casting config object: %s", ctx.Value("config")) } // Save session only if the session was extended. if extendSessionLifetime(sessionData, cfg.SessionLifeTime) { sessionData.ExpiresAt = time.Now().Add(cfg.SessionLifeTime) session.Save(r, w) } authenticatedContext := context.WithValue(ctx, "sessionData", sessionData) return h(authenticatedContext, w, r) } }
func saveUserToSessionAndSendHome(w http.ResponseWriter, r *http.Request, session *sessions.Session, userName string, id int) { session.Values["UserName"] = userName session.Values["Id"] = id err := session.Save(r, w) if err != nil { log.Fatal(err) } http.Redirect(w, r, "/", http.StatusFound) }
// Remove all current user information from the session object func (c *CAS) removeCurrentUserFromSession(w http.ResponseWriter, req *http.Request, session *sessions.Session) *CASServerError { // Delete current user from session delete(session.Values, "currentUser") // Save the modified session err := session.Save(req, w) if err != nil { return &FailedToDeleteSessionError } return nil }
// Token will return a token for the specified URL. SingleToken is ignored. func TokenWithPath(w http.ResponseWriter, r *http.Request, sess *sessions.Session, urlPath string) string { // Generate the map if it doesn't exist if _, ok := sess.Values[TokenName]; !ok { sess.Values[TokenName] = make(StringMap) } sessMap := sess.Values[TokenName].(StringMap) if _, ok := sessMap[urlPath]; !ok { sessMap[urlPath] = generate(TokenLength) sess.Save(r, w) } return sessMap[urlPath] }
func loginHandler(res http.ResponseWriter, r *http.Request, session *sessions.Session, ctx *pongo2.Context) (*string, error) { var ( username = strings.ToLower(r.FormValue("username")) password = fmt.Sprintf("%x", sha1.Sum([]byte(cfg.PasswordSalt+r.FormValue("password")))) ) if !storage.IsPresent(createUserFilename(username)) { (*ctx)["error"] = true return stringPointer("login.html"), nil } userFileRaw, err := storage.Read(createUserFilename(username)) if err != nil { fmt.Printf("ERR: Unable to read user file: %s\n", err) (*ctx)["error"] = true return stringPointer("login.html"), nil } userFile, _ := readDataObject(userFileRaw) if userFile.MetaData.Password != password { (*ctx)["error"] = true return stringPointer("login.html"), nil } auth, ok := session.Values["authorizedAccounts"].(authorizedAccounts) if !ok { auth = authorizedAccounts{} } for i, v := range auth { if v.Name == username { http.Redirect(res, r, fmt.Sprintf("u/%d/overview", i), http.StatusFound) return nil, nil } } auth = append(auth, authorizedAccount{ Name: username, UserFile: createUserFilename(username), }) session.Values["authorizedAccounts"] = auth if err := session.Save(r, res); err != nil { return nil, err } http.Redirect(res, r, fmt.Sprintf("u/%d/overview", len(auth)-1), http.StatusFound) return nil, nil }
func HomeHandler(w http.ResponseWriter, r *http.Request) { var session *sessions.Session s, err := store.Get(r, "session-name") if err != nil { log.Println("error fetching session:", err) s, _ := store.New(r, "session-name") session = s } else { session = s } state := randomString(64) session.Values["state"] = state session.Save(r, w) if err := Views.Lookup("home.ghtml").Execute(w, struct{}{}); err != nil { log.Printf("error executing view template: %v", err) } }
func (sc SessionController) SaveSession(w http.ResponseWriter, r *http.Request, s *sessions.Session) { err := s.Save(r, w) if err != nil { log.Println("ERROR: SessionController: SaveSession: " + err.Error()) } }
//ExtendExpiration pushes out the expiration of the session cookie to a further time //this is done to keep a user logged in automatically if they use the app frequently func ExtendExpiration(session *sessions.Session, w http.ResponseWriter, r *http.Request) { session.Options = options session.Save(r, w) return }
//Save saves any new session data to an existing session //write the new values to it (after using AddValue) func Save(session *sessions.Session, w http.ResponseWriter, r *http.Request) { session.Save(r, w) return }
func endSession(s *sessions.Session, w http.ResponseWriter, r *http.Request) { s.Options = &sessions.Options{MaxAge: -1} s.Save(r, w) }
func loginHandler(w http.ResponseWriter, r *http.Request) error { ctx := context.Get(r, TemplateContext).(map[string]interface{}) ctx["Title"] = "Login" if r.Method == "GET" { return renderTemplate(w, "login", ctx) } session, err := store.Get(r, "flashes") if err != nil { return err } if err := r.ParseForm(); err != nil { return err } lschema := &LoginSchema{} decoder := schema.NewDecoder() if err := decoder.Decode(lschema, r.PostForm); err != nil { return err } formErrors := []string{} if !govalidator.IsEmail(lschema.Email) { if lschema.Email == "" { formErrors = append(formErrors, "Email cannot be blank") } else { formErrors = append(formErrors, fmt.Sprintf("%s is not a valid email address", lschema.Email)) } } if lschema.Password == "" { formErrors = append(formErrors, "Password cannot be blank") } if len(formErrors) > 0 { for _, msg := range formErrors { session.AddFlash(msg, "danger") } session.Save(r, w) http.Redirect(w, r, reverse("login"), http.StatusSeeOther) return nil } userbytes, err := database.Get(uint64(1), config.BucketNameUser) if err != nil { formErrors = append(formErrors, "Email and password did not match") } user := DeserializeUser(userbytes) if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(lschema.Password)); err != nil { formErrors = append(formErrors, "Email and password did not match") } if len(formErrors) > 0 { for _, msg := range formErrors { session.AddFlash(msg, "danger") } session.Save(r, w) http.Redirect(w, r, reverse("login"), http.StatusSeeOther) return nil } var authsession *sessions.Session authsession, err = store.Get(r, "auth") if err != nil { return err } authsession.Values["userID"] = user.ID authsession.Save(r, w) http.Redirect(w, r, reverse("url-index"), http.StatusSeeOther) return nil }
func deleteSession(session *sessions.Session, w http.ResponseWriter, r *http.Request) { session.Options = &sessions.Options{MaxAge: -1} session.Save(r, w) }
func logoutHandler(res http.ResponseWriter, r *http.Request, session *sessions.Session, ctx *pongo2.Context) (*string, error) { session.Values["authorizedAccounts"] = authorizedAccounts{} session.Save(r, res) http.Redirect(res, r, "overview", http.StatusFound) return nil, nil }
func (u *User) saveSession(session *sessions.Session, w http.ResponseWriter, r *http.Request) error { session.Values["nickname"] = u.Nickname session.Values["email"] = u.Email return session.Save(r, w) }