I'm working on a login system in Go (Golang). Previously, I was using Gorilla Sessions for this, but I wanted to see if I could reinvent the wheel and make it simpler.
Also, I don't need to store many user values—just one: whether a user is logged in or not. For this, I decided to use a map.
sessions := make(map[string]bool)
When a user tries to login, this function gets called.
func tryLogin(username, password string) (http.Cookie, error) {
if exists := db.UserExists(username, password); !exists {
return http.Cookie{},
errors.New("The username or password you entered isn't correct.")
}
sid, err := randString(32)
if err != nil {
return http.Cookie{}, err
}
sessions[sid] = true
loginCookie := http.Cookie{
Name: "id",
Value: sid,
MaxAge: int((time.Hour * 12).Seconds()),
HttpOnly: true,
Domain: "mydomain.com",
Path: "/admin/",
}
return loginCookie, nil
}
My randString
function, which I use to generate a session ID, just reads random bytes and base64 encodes them.
func randString(size int) (string, error) {
buf := make([]byte, size)
if _, err := rand.Read(buf); err != nil {
log.Println(err)
return "", errors.New("Couldn't generate random string")
}
return base64.URLEncoding.EncodeToString(buf)[:size], nil
}
If a user exists in my database, then they get redirected to an admin area. One of the first things I do on every admin page is call sessionExists
to make sure they're still logged in.
func sessionExists(req *http.Request) bool {
cookie, err := req.Cookie("id")
if err == http.ErrNoCookie {
return false
} else if err != nil {
log.Println(err)
return false
}
if _, exists := sessions[cookie.Value]; !exists {
return false
}
return true
}
If sessionExists
returns false
, then I redirect the user to the login page.
I don't currently have HTTPS working, so I can't turn on the secure flag on my login cookie. But besides that, would this design provide adequate protection against intruders?