Login/logout issues

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)
	}
}

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.

1 Like

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

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)
1 Like

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

302 is more convenient.

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

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.