Login/logout issues


(Deepak Singh Kushwah) #1

Hello Guys, I am new to go and I am working on simple login/logout process. I am able to login user and logout, but if I logout user for second time and logged in back, I am unable to logged out this time. First time when user logged in, on /test url I show username and when logout first time, it reset cookie. But if I login again and logout, it do not reset cookie for login validation check. Here is my code, please help.

package main

import (
	"log"
	"net/http"
	"text/template"

	"github.com/gorilla/sessions"

	"github.com/gorilla/mux"
)

var t *template.Template
var store *sessions.CookieStore

func init() {
	t = template.Must(template.ParseGlob("templates/*.html"))
	store = sessions.NewCookieStore([]byte("t0p-s3cr3t"))
	store.Options.HttpOnly = true
}

func main() {
	r := mux.NewRouter()
	r.HandleFunc("/hello", helloHandler).Methods("GET")
	r.HandleFunc("/forbidden", forbiddenHandler).Methods("GET")

	r.HandleFunc("/login", loginGetHandler).Methods("GET")
	r.HandleFunc("/login", loginPostHandler).Methods("POST")

	r.HandleFunc("/test", testHandler).Methods("GET")
	r.HandleFunc("/logout", logoutHandler)

	r.HandleFunc("/", handler).Methods("GET")

	fs := http.FileServer(http.Dir("./static/"))
	r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", fs))

	http.Handle("/", r)
	http.ListenAndServe(":8080", nil)
}

func loginGetHandler(w http.ResponseWriter, r *http.Request) {
	page := struct {
		PageTitle string
	}{
		PageTitle: "Login Here",
	}
	t.ExecuteTemplate(w, "login.html", page)
}

func loginPostHandler(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	username := r.PostForm.Get("username")
	session, _ := store.Get(r, "session")
	session.Values["username"] = username
	session.Save(r, w)
	http.Redirect(w, r, "/test", 301)
}
func handler(w http.ResponseWriter, r *http.Request) {
	page := struct {
		PageTitle string
		Name      string
		Age       int
	}{
		PageTitle: "Welcome to new world of golang",
		Name:      "Deepak Singh Kushwah",
		Age:       36,
	}
	t.ExecuteTemplate(w, "index.html", page)
}
func helloHandler(w http.ResponseWriter, r *http.Request) {
	page := struct {
		PageTitle string
		Name      string
		Age       int
	}{
		PageTitle: "Hello World Handler",
		Name:      "Hello World",
		Age:       40,
	}
	t.ExecuteTemplate(w, "index.html", page)
}

func forbiddenHandler(w http.ResponseWriter, r *http.Request) {
	page := struct {
		PageTitle string
		Name      string
	}{
		PageTitle: "403",
		Name:      "403",
	}
	t.ExecuteTemplate(w, "forbidden.html", page)
}

func testHandler(w http.ResponseWriter, r *http.Request) {
	session, _ := store.Get(r, "session")
	untyped, ok := session.Values["username"]
	if !ok {
		http.Redirect(w, r, "/forbidden", 301)
		return
	}
	username, ok := untyped.(string)
	if !ok || username == "" {
		http.Redirect(w, r, "/forbidden", 301)
		return
	}
	page := struct {
		PageTitle string
		Name      string
	}{
		PageTitle: "TEST Handler",
		Name:      username,
	}
	t.ExecuteTemplate(w, "test.html", page)
}

func loginCheck(r *http.Request) bool {
	session, _ := store.Get(r, "session")
	untyped, ok := session.Values["username"]
	if !ok {
		return false
	}
	_, ok = untyped.(string)
	if !ok {
		return false
	}
	return true
}
func logoutHandler(w http.ResponseWriter, r *http.Request) {
	session, err := store.Get(r, "session")
	checkErr(err)
	session.Values["username"] = ""
	err = session.Save(r, w)
	checkErr(err)
	http.Redirect(w, r, "/", 301)
}

func checkErr(e error) {
	if e != nil {
		log.Panic(e)
	}
}

(Johan Dahl) #2

Don’t use 301 which is moved permanently. It teaches your browser that going to this url isn’t necessary because it has moved to / . Use 303 See other instead.


(Kristoffer Berdal) #3

Hey! Great that you have managed to solve the problem on your end! Could you perhaps share with us what your solution was?


(George Calianu) #4

Instead of using numeric codes you can use some constants representing HTTP status codes as registered with IANA (see https://golang.org/src/net/http/status.go).

http.Redirect(w, r, "/", http.StatusSeeOther)

(Deepak Singh Kushwah) #5

yes, I used 302 insted of 301 and it solved. Thank you all for your support.


(Ali Koyuncu) #6

302 is more convenient.


(Johan Dahl) #7

But 303 is better because it translate all requests to GET so if you redirect from a POST, DELETE, UPDATE etc will it be changed to a GET automagically (which is what you want in 99% of the cases). See this explanation https://serverfault.com/questions/391181/examples-of-302-vs-303 for example